{"id":2219728,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2219728/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-i2c/patch/20260404021920.359902-1-nissampa@cisco.com/","project":{"id":35,"url":"http://patchwork.ozlabs.org/api/1.1/projects/35/?format=json","name":"Linux I2C development","link_name":"linux-i2c","list_id":"linux-i2c.vger.kernel.org","list_email":"linux-i2c@vger.kernel.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20260404021920.359902-1-nissampa@cisco.com>","date":"2026-04-04T02:19:20","name":"at24: add SMBus fallback for adapters lacking I2C_FUNC_I2C","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"975d3d902d17a36e85546eebfb201e0587bff83d","submitter":{"id":93051,"url":"http://patchwork.ozlabs.org/api/1.1/people/93051/?format=json","name":"Nishanth Sampath Kumar","email":"nissampa@cisco.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linux-i2c/patch/20260404021920.359902-1-nissampa@cisco.com/mbox/","series":[{"id":498693,"url":"http://patchwork.ozlabs.org/api/1.1/series/498693/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-i2c/list/?series=498693","date":"2026-04-04T02:19:20","name":"at24: add SMBus fallback for adapters lacking I2C_FUNC_I2C","version":1,"mbox":"http://patchwork.ozlabs.org/series/498693/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2219728/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2219728/checks/","tags":{},"headers":{"Return-Path":"\n <linux-i2c+bounces-16956-incoming=patchwork.ozlabs.org@vger.kernel.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linux-i2c@vger.kernel.org"],"Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=cisco.com header.i=@cisco.com header.a=rsa-sha256\n header.s=iport01 header.b=T/rGlW71;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=172.234.253.10; helo=sea.lore.kernel.org;\n envelope-from=linux-i2c+bounces-16956-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)","smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com\n header.b=\"T/rGlW71\"","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=173.37.142.95","smtp.subspace.kernel.org;\n dmarc=pass (p=reject dis=none) header.from=cisco.com","smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=cisco.com"],"Received":["from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fnfV61QSGz1yD3\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 04 Apr 2026 13:21:34 +1100 (AEDT)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id C6B2F300DF70\n\tfor <incoming@patchwork.ozlabs.org>; Sat,  4 Apr 2026 02:20:37 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 64F4920D4FF;\n\tSat,  4 Apr 2026 02:20:36 +0000 (UTC)","from alln-iport-8.cisco.com (alln-iport-8.cisco.com [173.37.142.95])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 2838A35893;\n\tSat,  4 Apr 2026 02:20:33 +0000 (UTC)","from rcdn-l-core-01.cisco.com ([173.37.255.138])\n  by alln-iport-8.cisco.com with ESMTP/TLS/TLS_AES_256_GCM_SHA384;\n 04 Apr 2026 02:19:24 +0000","from sjc-ads-2636.cisco.com (sjc-ads-2636.cisco.com [171.70.32.71])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n\t(No client certificate requested)\n\tby rcdn-l-core-01.cisco.com (Postfix) with ESMTPS id A9350180001C5;\n\tSat,  4 Apr 2026 02:19:24 +0000 (GMT)","by sjc-ads-2636.cisco.com (Postfix, from userid 470863)\n\tid 3B440CBEF83; Fri,  3 Apr 2026 19:19:24 -0700 (PDT)"],"ARC-Seal":"i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1775269236; cv=none;\n b=oiayYXfHcMw/b3EIIIAlcIvou41hMfXJwvlJjgbZxGfZeWGChTXqaINuTH3+fcQCQssfg7sNIrraRBut/VEqYlDZqlLud0fZomlquODKOM4+w2v/oxOqum/RW43G73rn3S3vIB4QKLLO+QFwyoDtzyZjEV8atocFpqfMsNLG8oE=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1775269236; c=relaxed/simple;\n\tbh=NF8qIpmHVsbcu3sHqesh1NPyNm6zE60AqBXWscwLYRU=;\n\th=From:To:Cc:Subject:Date:Message-Id:MIME-Version;\n b=O3rNiOUV5XJVXY07xydfWsCaXWkx7CiQXBkN2ukeDtRsKwWq2gXB4xg6m+A3lhl5rYoNE80foqQf0odpEfWCg/MV5kGeC39q0FXilRojUl82pptoJFYjXHbOki8sEHP9OZQ1gPrGyDb5ZASswHYiibyR3oiYWlGetyb+eX+NQOA=","ARC-Authentication-Results":"i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=reject dis=none) header.from=cisco.com;\n spf=pass smtp.mailfrom=cisco.com;\n dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com\n header.b=T/rGlW71; arc=none smtp.client-ip=173.37.142.95","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n  d=cisco.com; i=@cisco.com; l=10769; q=dns/txt;\n  s=iport01; t=1775269234; x=1776478834;\n  h=from:to:cc:subject:date:message-id:mime-version:\n   content-transfer-encoding;\n  bh=SFLadLAyF1PhMfay+CG6tg8s4lYpQFfVhza6etmNhns=;\n  b=T/rGlW712Ejc3x+PiVTl3j3+y5RddMFO8zE3UoJEfgoXyMKy6B8VUNv/\n   dpEzup2DzXQL0rj+DydFD7xpQ3gl8zLv/QljTqCibDxX2Jn30+o2nIgYs\n   u9AayU9XjYIUwFF88brJajY+U/Jyz2V8XC4w5hjBy4aItatWaW2/kW4xW\n   7DBdY3AfUiJs5QMCEcgem+ITuHub164H7dCUfjuatvZZnLajIYbKpzptq\n   a64ch9kXHFXkykkMIv84qVhRWysBr9Q4XrWjynIzvlq32LfalkTV5EAgG\n   01zD6J6lOiApkoQl1qhakg/OekhzhYTgMNvhDkNe8EFWs1BqkW5D4DmcQ\n   g==;","X-CSE-ConnectionGUID":"2AYD/fHITjm82Jm7/s0c5w==","X-CSE-MsgGUID":"8VNhtYT4Rh682qZK8nw3DQ==","X-IPAS-Result":"\n A0ACAAA6dNBp/4r/Ja1aGQEBAQEBAQEBAQEBAQEBAQEBARIBAQEBAQEBAQEBAQGBfAQBAQEBAQsBglaBUEJJjHOJWIEWnQeBfw8BAQEPUQQBAYUHjSwCJjQJDgECBAEBAQEDAgMBAQEBAQEBAQEBAQsBAQUBAQECAQcFgQ4ThlyGXSsLAUaBDDsJgwKCdAIBtSqBeTOBAd4+gWQBCxWBOAGNWXSEeicVBoFJRIEVgnJ2gVqCMIZ9BIMcFIQZBoJlgzIBhh9IgR4DWSwBVRMNCgsHBYFmAzUSKhUyPDIdgSM+F4EMGwcFgUuHGnRtgRODfGYDCxgNSBEsNxQbBD5uB4tRKIE8CFIgexOBJ4E2DD2SYAkBkjyBNYpKlQ+EJqFYGjOEBJQVklEBLodlkHOjXH2EaDaBMjyBWTMaCBsVgyJSGQ+OKgMWyQojNT4BBwIHDgKBc5AAgX0BAQ","IronPort-Data":"A9a23:6NIcp6s3/taarh863Whdxho3fefnVE5fMUV32f8akzHdYApBsoF/q\n tZmKWmEOarZNmfwKI9+O4i09h9U7ZDcyoVnGws/r3wxEn5HgMeUXt7xwmUckM+xwmwvaGo9s\n q3yv/GZdJhcokf0/0nrav666yEgiclkf5KkYMbcICd9WAR4fykojBNnioYRj5Vh6TSDK1vlV\n eja/YuFYzdJ5xYuajhKs/7b80s11BjPkGpwUmIWNKgjUGD2zxH5PLpHTYmtIn3xRJVjH+LSb\n 47r0LGj82rFyAwmA9Wjn6yTWhVirmn6ZFXmZtJ+AsBOszAazsAA+v9T2Mk0NS+7vw60c+VZk\n 72hg3AfpTABZcUgkMxFO/VR/roX0aduoNcrKlDn2SCfItGvn3bEm51T4E8K0YIwoM9GLSZA1\n d0kKjVdNDKG2KWtmLnmVbw57igjBJGD0II3oHpsy3TdSP0hW52GG/yM7t5D1zB2jcdLdRrcT\n 5NGMnw0M1KaPkAJYwxHYH49tL/Aan3XdTxDs1uQvaMf6GnIxws327/oWDbQUoPSFJkFzx7B+\n goq+UypPDcaKO2jlQCFrCL2n93szSXkA64rQejQGvlCxQf7KnYoIBQMU1eTqOO/hkT4V983A\n 0YO9S4Gp6c++VLtVt2VdxKirXGHvjYYWtxNA+M99QeBw7bV5ADfAXILJhZFado7pIo3HzcCy\n FCEhZXqCCZpvbnTTmiSnp+QrDWvKW0WIHUEaCssUwQI+Z/grZs1gxaJScxseJNZlfXvEj32h\n jTPpy8kivBL1IgA1r6w+hbMhDfESoX1czPZLz7/BgqNhj6Vrqb+D2B0wTA3Ncp9Ebs=","IronPort-HdrOrdr":"A9a23:WxPP662nMioDX86uv0d/KQqjBLkkLtp133Aq2lEZdPWaSKOlfq\n eV7ZEmPHDP6Qr5NEtMpTniAtjjfZqjz/5ICOAqVN/INjUO01HHEGgN1+ffKkXbak7DHio379\n YGT0C4Y+eAaWRHsQ==","X-Talos-CUID":"\n 9a23:KShmKWgOtghcS924HkTbAf7U8jJuKFTs4DDeA26EC2M5Ep+QFhiLoKg5jJ87","X-Talos-MUID":"\n 9a23:zaYkQg/f+wTON1sQQIGPvHOQf5dWxaSyOXxRq5VY65OdBw8gPSjGoA3iFw==","X-IronPort-Anti-Spam-Filtered":"true","X-IronPort-AV":"E=Sophos;i=\"6.23,158,1770595200\";\n   d=\"scan'208\";a=\"709489014\"","From":"Nishanth Sampath Kumar <nissampa@cisco.com>","To":"brgl@bgdev.pl","Cc":"linux-i2c@vger.kernel.org,\n\tlinux-kernel@vger.kernel.org,\n\tarnd@arndb.de,\n\tgregkh@linuxfoundation.org,\n\tNishanth Sampath Kumar <nissampa@cisco.com>","Subject":"[PATCH] at24: add SMBus fallback for adapters lacking I2C_FUNC_I2C","Date":"Fri,  3 Apr 2026 19:19:20 -0700","Message-Id":"<20260404021920.359902-1-nissampa@cisco.com>","X-Mailer":"git-send-email 2.35.6","Precedence":"bulk","X-Mailing-List":"linux-i2c@vger.kernel.org","List-Id":"<linux-i2c.vger.kernel.org>","List-Subscribe":"<mailto:linux-i2c+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:linux-i2c+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","X-Outbound-SMTP-Client":"171.70.32.71, sjc-ads-2636.cisco.com","X-Outbound-Node":"rcdn-l-core-01.cisco.com"},"content":"AMD PIIX4 SMBus adapters, present on AMD SP5/EPYC-based platforms\n(including Cisco 8000 series routers), support SMBUS_BYTE_DATA and\nSMBUS_WORD_DATA but lack I2C_FUNC_I2C and I2C_FUNC_SMBUS_I2C_BLOCK.\nThis causes two distinct failures:\n\n1. AT24_FLAG_ADDR16 EEPROMs (e.g. 24c64 syseeprom):\n   regmap_get_i2c_bus() returns -ENOTSUPP (-524) for reg_bits=16\n   because neither I2C_FUNC_I2C nor I2C_FUNC_SMBUS_I2C_BLOCK is set.\n   The driver probe fails entirely with:\n     at24 3-0055: probe with driver at24 failed with error -524\n\n2. 8-bit addressed EEPROMs (e.g. 24c02 fan EEPROMs) behind a pca9548\n   mux on a PIIX4 child adapter: regmap selects regmap_i2c_smbus_i2c_block\n   which fails at runtime even though SMBUS_BYTE_DATA is available.\n\nAdd two SMBus-primitive fallback paths, selected after chip flags are\nfully resolved (i.e. after flags = cdata->flags and DT address-width\noverrides):\n\n  smbus_addr16_fallback (AT24_FLAG_ADDR16 set):\n    READ:  i2c_smbus_write_byte_data(client, addr_hi, addr_lo) sets\n           the 16-bit address pointer; repeated i2c_smbus_read_byte()\n           fetches bytes sequentially (EEPROM auto-increments pointer).\n    WRITE: i2c_smbus_write_word_data() encodes address + data byte\n           in one SMBus WORD transaction.\n\n  smbus_addr8_fallback (AT24_FLAG_ADDR16 not set):\n    READ:  i2c_smbus_read_byte_data(client, (u8)offset) per byte.\n    WRITE: i2c_smbus_write_byte_data(client, (u8)offset, data) per byte.\n\nBoth paths bypass regmap for I/O. A regmap init retry with reg_bits=8\nis added so that probe succeeds on adapters that reject the initial\nregmap configuration.\n\nThe fallback is only activated when i2c_check_functionality() confirms\nboth SMBUS_BYTE_DATA and SMBUS_WORD_DATA are present, ensuring no\nregression on adapters that support full I2C transfers.\n\nSigned-off-by: Nishanth Sampath Kumar <nissampa@cisco.com>\n---\n drivers/misc/eeprom/at24.c | 183 +++++++++++++++++++++++++++++++++++-\n 1 file changed, 182 insertions(+), 1 deletion(-)","diff":"--- a/drivers/misc/eeprom/at24.c\n+++ b/drivers/misc/eeprom/at24.c\n@@ -88,6 +88,11 @@\n \tstruct regulator *vcc_reg;\n \tvoid (*read_post)(unsigned int off, char *buf, size_t count);\n \n+\t/* SMBus-only fallback for EEPROMs on PIIX4 adapters */\n+\tbool smbus_addr16_fallback;\n+\tbool smbus_addr8_fallback;\n+\tstruct i2c_client *smbus_client;\n+\n \t/*\n \t * Some chips tie up multiple I2C addresses; dummy devices reserve\n \t * them for us.\n@@ -343,6 +348,139 @@\n \treturn count;\n }\n \n+/* forward declaration needed by at24_smbus_write below */\n+static size_t at24_adjust_write_count(struct at24_data *at24,\n+\t\t\t\t      unsigned int offset, size_t count);\n+\n+/*\n+ * SMBus primitive fallback for 16-bit addressed EEPROMs.\n+ *\n+ * PIIX4 SMBus supports BYTE_DATA and WORD_DATA but NOT I2C_FUNC_I2C or\n+ * I2C_FUNC_SMBUS_I2C_BLOCK, so regmap_get_i2c_bus() returns -ENOTSUPP\n+ * for reg_bits=16.  We bypass regmap entirely for the I/O path:\n+ *\n+ *  READ : write_byte_data(addr_hi, addr_lo) sets the 16-bit EEPROM\n+ *         address pointer, then read_byte() fetches bytes one-by-one\n+ *         (EEPROM auto-increments the pointer after each read).\n+ *\n+ *  WRITE: write_word_data(addr_hi, cpu_to_le16((data<<8)|addr_lo))\n+ *         encodes the address and data byte in one SMBus word write.\n+ */\n+static ssize_t at24_smbus_read(struct at24_data *at24, char *buf,\n+\t\t\t       unsigned int offset, size_t count)\n+{\n+\tstruct i2c_client *client = at24->smbus_client;\n+\tunsigned long timeout, read_time;\n+\tu8 addr_hi = (offset >> 8) & 0xff;\n+\tu8 addr_lo = offset & 0xff;\n+\tssize_t ret;\n+\tsize_t i;\n+\n+\tcount = at24_adjust_read_count(at24, offset, count);\n+\n+\ttimeout = jiffies + msecs_to_jiffies(at24_write_timeout);\n+\tdo {\n+\t\tread_time = jiffies;\n+\n+\t\t/* Set 16-bit address pointer: command=addr_hi, value=addr_lo */\n+\t\tret = i2c_smbus_write_byte_data(client, addr_hi, addr_lo);\n+\t\tif (ret < 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* Read bytes sequentially -- EEPROM auto-increments pointer */\n+\t\tfor (i = 0; i < count; i++) {\n+\t\t\tret = i2c_smbus_read_byte(client);\n+\t\t\tif (ret < 0)\n+\t\t\t\tgoto retry;\n+\t\t\tbuf[i] = (u8)ret;\n+\t\t}\n+\t\tdev_dbg(&client->dev, \"smbus read %zu@%u --> ok\\n\", count, offset);\n+\t\treturn count;\n+retry:\n+\t\tusleep_range(1000, 1500);\n+\t} while (time_before(read_time, timeout));\n+\n+\treturn -ETIMEDOUT;\n+}\n+\n+static ssize_t at24_smbus_write(struct at24_data *at24, const char *buf,\n+\t\t\t\tunsigned int offset, size_t count)\n+{\n+\tstruct i2c_client *client = at24->smbus_client;\n+\tunsigned long timeout, write_time;\n+\tsize_t i;\n+\tint ret;\n+\n+\t/* Write one byte at a time (page writes need raw I2C transfers) */\n+\tcount = at24_adjust_write_count(at24, offset, count);\n+\n+\tfor (i = 0; i < count; i++, offset++) {\n+\t\ttimeout = jiffies + msecs_to_jiffies(at24_write_timeout);\n+\t\tdo {\n+\t\t\twrite_time = jiffies;\n+\t\t\t/*\n+\t\t\t * command  = addr[15:8]\n+\t\t\t * word LSB = addr[7:0]\n+\t\t\t * word MSB = data byte\n+\t\t\t * EEPROM: set 16-bit address then write one data byte.\n+\t\t\t */\n+\t\t\tret = i2c_smbus_write_word_data(client,\n+\t\t\t\t\t(offset >> 8) & 0xff,\n+\t\t\t\t\tcpu_to_le16(((u16)(u8)buf[i] << 8) |\n+\t\t\t\t\t\t    (offset & 0xff)));\n+\t\t\tif (!ret) {\n+\t\t\t\tdev_dbg(&client->dev, \"smbus write 1@%u --> ok\\n\",\n+\t\t\t\t\toffset);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tusleep_range(1000, 1500);\n+\t\t} while (time_before(write_time, timeout));\n+\n+\t\tif (ret)\n+\t\t\treturn (i > 0) ? (ssize_t)i : -ETIMEDOUT;\n+\t}\n+\n+\treturn count;\n+}\n+\n+static ssize_t at24_smbus8_read(struct at24_data *at24, char *buf,\n+\t\t\t\tunsigned int offset, size_t count)\n+{\n+\tstruct i2c_client *client = at24->smbus_client;\n+\tsize_t i;\n+\tint ret;\n+\n+\tcount = at24_adjust_read_count(at24, offset, count);\n+\n+\tfor (i = 0; i < count; i++) {\n+\t\tret = i2c_smbus_read_byte_data(client, (u8)(offset + i));\n+\t\tif (ret < 0)\n+\t\t\treturn ret;\n+\t\tbuf[i] = (u8)ret;\n+\t}\n+\tdev_dbg(&client->dev, \"smbus8 read %zu@%u --> ok\\n\", count, offset);\n+\treturn count;\n+}\n+\n+static ssize_t at24_smbus8_write(struct at24_data *at24, const char *buf,\n+\t\t\t\t unsigned int offset, size_t count)\n+{\n+\tstruct i2c_client *client = at24->smbus_client;\n+\tsize_t i;\n+\tint ret;\n+\n+\tcount = at24_adjust_write_count(at24, offset, count);\n+\n+\tfor (i = 0; i < count; i++) {\n+\t\tret = i2c_smbus_write_byte_data(client, (u8)(offset + i),\n+\t\t\t\t\t\t(u8)buf[i]);\n+\t\tif (ret < 0)\n+\t\t\treturn (i > 0) ? (ssize_t)i : ret;\n+\t}\n+\tdev_dbg(&client->dev, \"smbus8 write %zu@%u --> ok\\n\", count, offset);\n+\treturn count;\n+}\n+\n static ssize_t at24_regmap_read(struct at24_data *at24, char *buf,\n \t\t\t\tunsigned int offset, size_t count)\n {\n@@ -353,6 +491,12 @@\n \tregmap = at24_translate_offset(at24, &offset);\n \tcount = at24_adjust_read_count(at24, offset, count);\n \n+\tif (at24->smbus_addr16_fallback)\n+\t\treturn at24_smbus_read(at24, buf, offset, count);\n+\n+\tif (at24->smbus_addr8_fallback)\n+\t\treturn at24_smbus8_read(at24, buf, offset, count);\n+\n \t/* adjust offset for mac and serial read ops */\n \toffset += at24->offset_adj;\n \n@@ -411,6 +555,13 @@\n \n \tregmap = at24_translate_offset(at24, &offset);\n \tcount = at24_adjust_write_count(at24, offset, count);\n+\n+\tif (at24->smbus_addr16_fallback)\n+\t\treturn at24_smbus_write(at24, buf, offset, count);\n+\n+\tif (at24->smbus_addr8_fallback)\n+\t\treturn at24_smbus8_write(at24, buf, offset, count);\n+\n \ttimeout = jiffies + msecs_to_jiffies(at24_write_timeout);\n \n \tdo {\n@@ -601,6 +752,8 @@\n \tbool i2c_fn_i2c, i2c_fn_block;\n \tunsigned int i, num_addresses;\n \tstruct at24_data *at24;\n+\tbool smbus_addr16_fallback;\n+\tbool smbus_addr8_fallback;\n \tbool full_power;\n \tstruct regmap *regmap;\n \tbool writable;\n@@ -611,6 +764,18 @@\n \ti2c_fn_block = i2c_check_functionality(client->adapter,\n \t\t\t\t\t       I2C_FUNC_SMBUS_WRITE_I2C_BLOCK);\n \n+\t/*\n+\t * Detect SMBus-only adapters (e.g. AMD PIIX4) that lack true I2C\n+\t * transfer capability.  Two cases:\n+\t *\n+\t * 1. No I2C_FUNC_I2C and no I2C_FUNC_SMBUS_I2C_BLOCK:\n+\t *    For 16-bit addressed EEPROMs (AT24_FLAG_ADDR16), bypass regmap\n+\t *    and use SMBus BYTE_DATA/WORD_DATA helpers.\n+\t *\n+\t * 2. No I2C_FUNC_I2C but I2C_FUNC_SMBUS_READ_I2C_BLOCK advertised\n+\t *    (PIIX4 mux children): regmap picks the block-read path which\n+\t *    fails at runtime.  For 8-bit addressed EEPROMs use BYTE_DATA.\n+\t */\n \tcdata = i2c_get_match_data(client);\n \tif (!cdata)\n \t\treturn -ENODEV;\n@@ -648,6 +813,33 @@\n \t\t}\n \t}\n \n+\t/*\n+\t * Detect SMBus-only adapters (e.g. AMD PIIX4) that lack true I2C\n+\t * capability.  Detection is done here, after flags has been resolved\n+\t * from cdata and any device-tree overrides.\n+\t */\n+\tsmbus_addr16_fallback = false;\n+\tsmbus_addr8_fallback = false;\n+\tif (!i2c_fn_i2c) {\n+\t\tbool has_byte = i2c_check_functionality(client->adapter,\n+\t\t\t\t\t\tI2C_FUNC_SMBUS_BYTE_DATA);\n+\t\tbool has_word = i2c_check_functionality(client->adapter,\n+\t\t\t\t\t\tI2C_FUNC_SMBUS_WORD_DATA);\n+\t\tif (has_byte && has_word) {\n+\t\t\t/*\n+\t\t\t * SMBus-only adapter (e.g. AMD PIIX4): no true I2C transfers.\n+\t\t\t * Choose fallback based on EEPROM address width.\n+\t\t\t */\n+\t\t\tif (flags & AT24_FLAG_ADDR16) {\n+\t\t\t\tsmbus_addr16_fallback = true;\n+\t\t\t\tdev_dbg(dev, \"SMBus-only adapter: enabling 16-bit addr SMBus fallback\\n\");\n+\t\t\t} else {\n+\t\t\t\tsmbus_addr8_fallback = true;\n+\t\t\t\tdev_dbg(dev, \"SMBus-only adapter: enabling 8-bit addr SMBus fallback\\n\");\n+\t\t\t}\n+\t\t}\n+\t}\n+\n \terr = device_property_read_u32(dev, \"size\", &byte_len);\n \tif (err)\n \t\tbyte_len = cdata->byte_len;\n@@ -681,10 +873,31 @@\n \tregmap_config.val_bits = 8;\n \tregmap_config.reg_bits = (flags & AT24_FLAG_ADDR16) ? 16 : 8;\n \tregmap_config.disable_locking = true;\n+\t/*\n+\t * Force reg_bits=8 when the SMBus fallback path is active so that\n+\t * regmap_get_i2c_bus() can pick regmap_smbus_byte and succeed on PIIX4.\n+\t * The actual 16-bit address I/O is done entirely by our helpers.\n+\t */\n+\tif (smbus_addr16_fallback && (flags & AT24_FLAG_ADDR16))\n+\t\tregmap_config.reg_bits = 8;\n \n \tregmap = devm_regmap_init_i2c(client, &regmap_config);\n-\tif (IS_ERR(regmap))\n-\t\treturn PTR_ERR(regmap);\n+\tif (IS_ERR(regmap)) {\n+\t\t/*\n+\t\t * For SMBus fallback paths the regmap is never used for I/O.\n+\t\t * If regmap init fails (e.g. adapter lacks I2C_FUNC_SMBUS_I2C_BLOCK\n+\t\t * at probe time), retry with a minimal byte config so probe succeeds.\n+\t\t */\n+\t\tif (smbus_addr16_fallback || smbus_addr8_fallback) {\n+\t\t\tstruct regmap_config smbus_config = regmap_config;\n+\n+\t\t\tsmbus_config.reg_bits = 8;\n+\t\t\tsmbus_config.val_bits = 8;\n+\t\t\tregmap = devm_regmap_init_i2c(client, &smbus_config);\n+\t\t}\n+\t\tif (IS_ERR(regmap))\n+\t\t\treturn PTR_ERR(regmap);\n+\t}\n \n \tat24 = devm_kzalloc(dev, struct_size(at24, client_regmaps, num_addresses),\n \t\t\t    GFP_KERNEL);\n@@ -700,6 +913,9 @@\n \tat24->num_addresses = num_addresses;\n \tat24->offset_adj = at24_get_offset_adj(flags, byte_len);\n \tat24->client_regmaps[0] = regmap;\n+\tat24->smbus_addr16_fallback = smbus_addr16_fallback;\n+\tat24->smbus_addr8_fallback = smbus_addr8_fallback;\n+\tat24->smbus_client = client;\n \n \tat24->vcc_reg = devm_regulator_get(dev, \"vcc\");\n \tif (IS_ERR(at24->vcc_reg))\n","prefixes":[]}