diff --git a/sys/dev/i2c/spdmem_i2c.c b/sys/dev/i2c/spdmem_i2c.c index 128fa313a651..a55a2227aad9 100644 --- a/sys/dev/i2c/spdmem_i2c.c +++ b/sys/dev/i2c/spdmem_i2c.c @@ -1,9 +1,10 @@ -/* $NetBSD: spdmem_i2c.c,v 1.10 2015/03/07 14:16:51 jmcneill Exp $ */ +/* $NetBSD: spdmem_i2c.c,v 1.11 2015/12/07 09:41:37 mlelstv Exp $ */ /* * Copyright (c) 2007 Nicolas Joly * Copyright (c) 2007 Paul Goyette * Copyright (c) 2007 Tobias Nygren + * Copyright (c) 2015 Michael van Elst * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,10 +33,14 @@ /* * Serial Presence Detect (SPD) memory identification + * + * JEDEC standard No. 21-C + * JEDEC document 4_01_06R24 + * - Definitions of the EE1004-v 4 Kbit Serial Presence Detect EEPROM [...] */ #include -__KERNEL_RCSID(0, "$NetBSD: spdmem_i2c.c,v 1.10 2015/03/07 14:16:51 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spdmem_i2c.c,v 1.11 2015/12/07 09:41:37 mlelstv Exp $"); #include #include @@ -49,13 +54,38 @@ __KERNEL_RCSID(0, "$NetBSD: spdmem_i2c.c,v 1.10 2015/03/07 14:16:51 jmcneill Exp #include /* Constants for matching i2c bus address */ -#define SPDMEM_I2C_ADDRMASK 0x3f8 +#define SPDMEM_I2C_ADDRMASK 0xfff8 #define SPDMEM_I2C_ADDR 0x50 +#define SPDCTL_I2C_ADDR 0x30 + +/* set write protection */ +#define SPDCTL_SWP0 (SPDCTL_I2C_ADDR + 1) +#define SPDCTL_SWP1 (SPDCTL_I2C_ADDR + 4) +#define SPDCTL_SWP2 (SPDCTL_I2C_ADDR + 5) +#define SPDCTL_SWP3 (SPDCTL_I2C_ADDR + 0) + +/* clear write protections */ +#define SPDCTL_CWP (SPDCTL_I2C_ADDR + 3) + +/* read protection status */ +#define SPDCTL_RPS0 (SPDCTL_I2C_ADDR + 1) +#define SPDCTL_RPS1 (SPDCTL_I2C_ADDR + 4) +#define SPDCTL_RPS2 (SPDCTL_I2C_ADDR + 5) +#define SPDCTL_RPS3 (SPDCTL_I2C_ADDR + 0) + +/* select page address */ +#define SPDCTL_SPA0 (SPDCTL_I2C_ADDR + 6) +#define SPDCTL_SPA1 (SPDCTL_I2C_ADDR + 7) + +/* read page address */ +#define SPDCTL_RPA (SPDCTL_I2C_ADDR + 6) struct spdmem_i2c_softc { struct spdmem_softc sc_base; i2c_tag_t sc_tag; - i2c_addr_t sc_addr; + i2c_addr_t sc_addr; /* EEPROM */ + i2c_addr_t sc_page0; + i2c_addr_t sc_page1; }; static int spdmem_i2c_match(device_t, cfdata_t, void *); @@ -65,7 +95,7 @@ static int spdmem_i2c_detach(device_t, int); CFATTACH_DECL_NEW(spdmem_iic, sizeof(struct spdmem_i2c_softc), spdmem_i2c_match, spdmem_i2c_attach, spdmem_i2c_detach, NULL); -static uint8_t spdmem_i2c_read(struct spdmem_softc *, uint8_t); +static uint8_t spdmem_i2c_read(struct spdmem_softc *, uint16_t); static int spdmem_i2c_match(device_t parent, cfdata_t match, void *aux) @@ -88,6 +118,8 @@ spdmem_i2c_match(device_t parent, cfdata_t match, void *aux) sc.sc_tag = ia->ia_tag; sc.sc_addr = ia->ia_addr; + sc.sc_page0 = SPDCTL_SPA0; + sc.sc_page1 = SPDCTL_SPA1; sc.sc_base.sc_read = spdmem_i2c_read; return spdmem_common_probe(&sc.sc_base); @@ -101,6 +133,8 @@ spdmem_i2c_attach(device_t parent, device_t self, void *aux) sc->sc_tag = ia->ia_tag; sc->sc_addr = ia->ia_addr; + sc->sc_page0 = SPDCTL_SPA0; + sc->sc_page1 = SPDCTL_SPA1; sc->sc_base.sc_read = spdmem_i2c_read; if (!pmf_device_register(self, NULL, NULL)) @@ -120,14 +154,28 @@ spdmem_i2c_detach(device_t self, int flags) } static uint8_t -spdmem_i2c_read(struct spdmem_softc *softc, uint8_t reg) +spdmem_i2c_read(struct spdmem_softc *softc, uint16_t addr) { - uint8_t val; + uint8_t reg, val; struct spdmem_i2c_softc *sc = (struct spdmem_i2c_softc *)softc; + static uint8_t dummy = 0; + + reg = addr & 0xff; iic_acquire_bus(sc->sc_tag, 0); - iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, ®, 1, - &val, 1, I2C_F_POLL); + + if (addr & 0x100) { + iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_page1, + &dummy, 1, NULL, 0, I2C_F_POLL); + iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, + ®, 1, &val, 1, I2C_F_POLL); + iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_page0, + &dummy, 1, NULL, 0, I2C_F_POLL); + } else { + iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, + ®, 1, &val, 1, I2C_F_POLL); + } + iic_release_bus(sc->sc_tag, 0); return val; diff --git a/sys/dev/ic/spdmemvar.h b/sys/dev/ic/spdmemvar.h index 1c4770bd3d77..b0066204cc7f 100644 --- a/sys/dev/ic/spdmemvar.h +++ b/sys/dev/ic/spdmemvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: spdmemvar.h,v 1.8 2015/12/06 09:31:20 msaitoh Exp $ */ +/* $NetBSD: spdmemvar.h,v 1.9 2015/12/07 09:41:37 mlelstv Exp $ */ /* * Copyright (c) 2007 Paul Goyette @@ -885,7 +885,7 @@ struct spdmem { #define SPDMEM_TYPE_MAXLEN 24 struct spdmem_softc { - uint8_t (*sc_read)(struct spdmem_softc *, uint8_t); + uint8_t (*sc_read)(struct spdmem_softc *, uint16_t); struct spdmem sc_spd_data; struct sysctllog *sc_sysctl_log; char sc_type[SPDMEM_TYPE_MAXLEN];