diff options
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/i2c/files.i2c | 7 | ||||
| -rw-r--r-- | sys/dev/i2c/spdmem_i2c.c | 122 | ||||
| -rw-r--r-- | sys/dev/ic/spdmem.c (renamed from sys/dev/i2c/spdmem.c) | 87 | ||||
| -rw-r--r-- | sys/dev/ic/spdmemreg.h (renamed from sys/dev/i2c/spdmemreg.h) | 6 | ||||
| -rw-r--r-- | sys/dev/ic/spdmemvar.h (renamed from sys/dev/i2c/spdmemvar.h) | 9 |
5 files changed, 152 insertions, 79 deletions
diff --git a/sys/dev/i2c/files.i2c b/sys/dev/i2c/files.i2c index abb6b658e66..e5098175872 100644 --- a/sys/dev/i2c/files.i2c +++ b/sys/dev/i2c/files.i2c @@ -1,4 +1,4 @@ -# $NetBSD: files.i2c,v 1.26 2010/02/22 03:50:56 pgoyette Exp $ +# $NetBSD: files.i2c,v 1.27 2010/03/24 00:31:41 pgoyette Exp $ defflag opt_i2cbus.h I2C_SCAN define i2cbus { } @@ -102,9 +102,8 @@ 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 +attach spdmem at iic with spdmem_iic +file dev/i2c/spdmem_i2c.c spdmem_iic # Memory Temp Sensor device sdtemp: sysmon_envsys diff --git a/sys/dev/i2c/spdmem_i2c.c b/sys/dev/i2c/spdmem_i2c.c new file mode 100644 index 00000000000..a4fca28898f --- /dev/null +++ b/sys/dev/i2c/spdmem_i2c.c @@ -0,0 +1,122 @@ +/* $NetBSD: spdmem_i2c.c,v 1.1 2010/03/24 00:31:41 pgoyette Exp $ */ + +/* + * Copyright (c) 2007 Nicolas Joly + * Copyright (c) 2007 Paul Goyette + * Copyright (c) 2007 Tobias Nygren + * 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. + */ + +/* + * Serial Presence Detect (SPD) memory identification + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: spdmem_i2c.c,v 1.1 2010/03/24 00:31:41 pgoyette Exp $"); + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/endian.h> +#include <sys/sysctl.h> +#include <machine/bswap.h> + +#include <dev/i2c/i2cvar.h> +#include <dev/ic/spdmemreg.h> +#include <dev/ic/spdmemvar.h> + +/* Constants for matching i2c bus address */ +#define SPDMEM_I2C_ADDRMASK 0x78 +#define SPDMEM_I2C_ADDR 0x50 + +struct spdmem_i2c_softc { + struct spdmem_softc sc_base; + i2c_tag_t sc_tag; + i2c_addr_t sc_addr; +}; + +static int spdmem_i2c_match(device_t, cfdata_t, void *); +static void spdmem_i2c_attach(device_t, device_t, void *); +SYSCTL_SETUP_PROTO(sysctl_spdmem_setup); + +static uint8_t spdmem_i2c_read(struct spdmem_softc *, uint8_t); + +CFATTACH_DECL_NEW(spdmem_iic, sizeof(struct spdmem_i2c_softc), + spdmem_i2c_match, spdmem_i2c_attach, NULL, NULL); + +static int +spdmem_i2c_match(device_t parent, cfdata_t match, void *aux) +{ + struct i2c_attach_args *ia = aux; + struct spdmem_i2c_softc sc; + + if (ia->ia_name) { + /* add other names as we find more firmware variations */ + if (strcmp(ia->ia_name, "dimm-spd")) + return 0; + } + + /* only do this lame test when not using direct config */ + if (ia->ia_name == NULL) { + if ((ia->ia_addr & SPDMEM_I2C_ADDRMASK) != SPDMEM_I2C_ADDR) + return 0; + } + + sc.sc_tag = ia->ia_tag; + sc.sc_addr = ia->ia_addr; + sc.sc_base.sc_read = spdmem_i2c_read; + + return spdmem_common_probe(&sc.sc_base); +} + +static void +spdmem_i2c_attach(device_t parent, device_t self, void *aux) +{ + struct spdmem_i2c_softc *sc = device_private(self); + struct i2c_attach_args *ia = aux; + + sc->sc_tag = ia->ia_tag; + sc->sc_addr = ia->ia_addr; + sc->sc_base.sc_read = spdmem_i2c_read; + + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + + spdmem_common_attach(&sc->sc_base, self); +} + +static uint8_t +spdmem_i2c_read(struct spdmem_softc *softc, uint8_t reg) +{ + uint8_t val; + struct spdmem_i2c_softc *sc = (struct spdmem_i2c_softc *)softc; + + 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; +} diff --git a/sys/dev/i2c/spdmem.c b/sys/dev/ic/spdmem.c index 03d201e0a98..269dabd4f90 100644 --- a/sys/dev/i2c/spdmem.c +++ b/sys/dev/ic/spdmem.c @@ -1,4 +1,4 @@ -/* $NetBSD: spdmem.c,v 1.18 2010/03/23 12:13:28 njoly Exp $ */ +/* $NetBSD: spdmem.c,v 1.1 2010/03/24 00:31:41 pgoyette Exp $ */ /* * Copyright (c) 2007 Nicolas Joly @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: spdmem.c,v 1.18 2010/03/23 12:13:28 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spdmem.c,v 1.1 2010/03/24 00:31:41 pgoyette Exp $"); #include <sys/param.h> #include <sys/device.h> @@ -44,15 +44,11 @@ __KERNEL_RCSID(0, "$NetBSD: spdmem.c,v 1.18 2010/03/23 12:13:28 njoly Exp $"); #include <machine/bswap.h> #include <dev/i2c/i2cvar.h> -#include <dev/i2c/spdmemreg.h> -#include <dev/i2c/spdmemvar.h> +#include <dev/ic/spdmemreg.h> +#include <dev/ic/spdmemvar.h> -static int spdmem_match(device_t, cfdata_t, void *); -static void spdmem_attach(device_t, device_t, void *); SYSCTL_SETUP_PROTO(sysctl_spdmem_setup); -static uint8_t spdmem_read(struct spdmem_softc *, uint8_t); - /* Routines for decoding spd data */ static void decode_edofpm(const struct sysctlnode *, device_t, struct spdmem *); static void decode_rom(const struct sysctlnode *, device_t, struct spdmem *); @@ -67,9 +63,6 @@ static void decode_size_speed(const struct sysctlnode *, int, int, int, int, bool, const char *, int); static void decode_voltage_refresh(device_t, struct spdmem *); -CFATTACH_DECL_NEW(spdmem, sizeof(struct spdmem_softc), - spdmem_match, spdmem_attach, NULL, NULL); - #define IS_RAMBUS_TYPE (s->sm_len < 4) static const char* spdmem_basic_types[] = { @@ -145,7 +138,7 @@ static uint16_t spdcrc16 (struct spdmem_softc *sc, int count) uint8_t val; crc = 0; for (j = 0; j <= count; j++) { - val = spdmem_read(sc, j); + val = (sc->sc_read)(sc, j); crc = crc ^ val << 8; for (i = 0; i < 8; ++i) if (crc & 0x8000) @@ -156,42 +149,24 @@ static uint16_t spdcrc16 (struct spdmem_softc *sc, int count) return (crc & 0xFFFF); } -static int -spdmem_match(device_t parent, cfdata_t match, void *aux) +int +spdmem_common_probe(struct spdmem_softc *sc) { - struct i2c_attach_args *ia = aux; - struct spdmem_softc sc; int cksum = 0; uint8_t i, val, spd_type; int spd_len, spd_crc_cover; uint16_t crc_calc, crc_spd; - if (ia->ia_name) { - /* add other names as we find more firmware variations */ - if (strcmp(ia->ia_name, "dimm-spd")) - return 0; - } - - /* only do this lame test when not using direct config */ - if (ia->ia_name == NULL) { - if ((ia->ia_addr & SPDMEM_ADDRMASK) != SPDMEM_ADDR) - return 0; - } - - sc.sc_tag = ia->ia_tag; - sc.sc_addr = ia->ia_addr; - - spd_type = spdmem_read(&sc, 2); + spd_type = (sc->sc_read)(sc, 2); /* For older memory types, validate the checksum over 1st 63 bytes */ if (spd_type <= SPDMEM_MEMTYPE_DDR2SDRAM) { for (i = 0; i < 63; i++) - cksum += spdmem_read(&sc, i); + cksum += (sc->sc_read)(sc, i); - val = spdmem_read(&sc, 63); + val = (sc->sc_read)(sc, 63); if (cksum == 0 || (cksum & 0xff) != val) { - aprint_debug("spd addr 0x%2x: ", sc.sc_addr); aprint_debug("spd checksum failed, calc = 0x%02x, " "spd = 0x%02x\n", cksum, val); return 0; @@ -201,7 +176,7 @@ spdmem_match(device_t parent, cfdata_t match, void *aux) /* For DDR3 and FBDIMM, verify the CRC */ else if (spd_type <= SPDMEM_MEMTYPE_DDR3SDRAM) { - spd_len = spdmem_read(&sc, 0); + spd_len = (sc->sc_read)(sc, 0); if (spd_len && SPDMEM_SPDCRC_116) spd_crc_cover = 116; else @@ -221,11 +196,10 @@ spdmem_match(device_t parent, cfdata_t match, void *aux) } if (spd_crc_cover > spd_len) return 0; - crc_calc = spdcrc16(&sc, spd_crc_cover); - crc_spd = spdmem_read(&sc, 127) << 8; - crc_spd |= spdmem_read(&sc, 126); + crc_calc = spdcrc16(sc, spd_crc_cover); + crc_spd = (sc->sc_read)(sc, 127) << 8; + crc_spd |= (sc->sc_read)(sc, 126); if (crc_calc != crc_spd) { - aprint_debug("spd addr 0x%2x: ", sc.sc_addr); aprint_debug("crc16 failed, covers %d bytes, " "calc = 0x%04x, spd = 0x%04x\n", spd_crc_cover, crc_calc, crc_spd); @@ -238,11 +212,9 @@ spdmem_match(device_t parent, cfdata_t match, void *aux) return 0; } -static void -spdmem_attach(device_t parent, device_t self, void *aux) +void +spdmem_common_attach(struct spdmem_softc *sc, device_t self) { - struct spdmem_softc *sc = device_private(self); - struct i2c_attach_args *ia = aux; struct spdmem *s = &(sc->sc_spd_data); const char *type; const char *rambus_rev = "Reserved"; @@ -251,19 +223,13 @@ spdmem_attach(device_t parent, device_t self, void *aux) unsigned int spd_len, spd_size; const struct sysctlnode *node = NULL; - sc->sc_tag = ia->ia_tag; - sc->sc_addr = ia->ia_addr; - - if (!pmf_device_register(self, NULL, NULL)) - aprint_error_dev(self, "couldn't establish power handler\n"); - /* * FBDIMM and DDR3 (and probably all newer) have a different * encoding of the SPD EEPROM used/total sizes */ - s->sm_len = spdmem_read(sc, 0); - s->sm_size = spdmem_read(sc, 1); - s->sm_type = spdmem_read(sc, 2); + s->sm_len = (sc->sc_read)(sc, 0); + s->sm_size = (sc->sc_read)(sc, 1); + s->sm_type = (sc->sc_read)(sc, 2); if (s->sm_type >= SPDMEM_MEMTYPE_FBDIMM) { spd_size = 64 << (s->sm_len & SPDMEM_SPDSIZE_MASK); @@ -292,7 +258,7 @@ spdmem_attach(device_t parent, device_t self, void *aux) if (spd_len > sizeof(struct spdmem)) spd_len = sizeof(struct spdmem); for (i = 3; i < spd_len; i++) - ((uint8_t *)s)[i] = spdmem_read(sc, i); + ((uint8_t *)s)[i] = (sc->sc_read)(sc, i); #ifdef DEBUG for (i = 0; i < spd_len; i += 16) { @@ -420,19 +386,6 @@ spdmem_attach(device_t parent, device_t self, void *aux) } } -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; -} - SYSCTL_SETUP(sysctl_spdmem_setup, "sysctl hw.spdmem subtree setup") { const struct sysctlnode *node; diff --git a/sys/dev/i2c/spdmemreg.h b/sys/dev/ic/spdmemreg.h index b6bd43feaf7..6b9f4b72a9d 100644 --- a/sys/dev/i2c/spdmemreg.h +++ b/sys/dev/ic/spdmemreg.h @@ -1,4 +1,4 @@ -/* $NetBSD: spdmemreg.h,v 1.3 2009/02/22 17:28:50 pgoyette Exp $ */ +/* $NetBSD: spdmemreg.h,v 1.1 2010/03/24 00:31:41 pgoyette Exp $ */ /* * Copyright (c) 2007 Paul Goyette @@ -28,10 +28,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -/* Constants for matching i2c bus address */ -#define SPDMEM_ADDRMASK 0x78 -#define SPDMEM_ADDR 0x50 - /* possible values for the memory type */ #define SPDMEM_MEMTYPE_FPM 0x01 #define SPDMEM_MEMTYPE_EDO 0x02 diff --git a/sys/dev/i2c/spdmemvar.h b/sys/dev/ic/spdmemvar.h index c935d405443..d0bd11a97d5 100644 --- a/sys/dev/i2c/spdmemvar.h +++ b/sys/dev/ic/spdmemvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: spdmemvar.h,v 1.7 2008/11/22 19:25:38 pgoyette Exp $ */ +/* $NetBSD: spdmemvar.h,v 1.1 2010/03/24 00:31:41 pgoyette Exp $ */ /* * Copyright (c) 2007 Paul Goyette @@ -514,9 +514,12 @@ struct spdmem { #define sm_selfrefresh sm_fpm.fpm_selfrefresh #define SPDMEM_TYPE_MAXLEN 16 + struct spdmem_softc { - i2c_tag_t sc_tag; - i2c_addr_t sc_addr; + uint8_t (*sc_read)(struct spdmem_softc *, uint8_t); struct spdmem sc_spd_data; char sc_type[SPDMEM_TYPE_MAXLEN]; }; + +int spdmem_common_probe(struct spdmem_softc *); +void spdmem_common_attach(struct spdmem_softc *, device_t); |
