From nobody Sat Feb 14 02:07:13 2026 Received: from mx0a-0024c301.pphosted.com (mx0a-0024c301.pphosted.com [148.163.149.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F2BB035DD15 for ; Thu, 12 Feb 2026 14:44:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=148.163.149.154 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770907480; cv=fail; b=ZxFeciHmzG7zwl7o4sgu2oHzOUe3YBsk1jNh4WIWurhD/gO7Spqd2No/gEl/2kJVzSspQEcoT8cLMG6M6vfSJtKgs2cWCjl5deDyHdWu46CSjQb2dPxs1xEma075iknP/l2IFgLNQoToJuzPmgGldn84ywPm5H1bk5THenXEZyI= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770907480; c=relaxed/simple; bh=S2qARm2EBlR5ULvIkhAtB8vBQ+JS5wcPaq4LTK6et6A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: Content-Type:MIME-Version; b=PIfCA1KTcHNh3lHje1b7kNiTUYAXgaFPRz75e5dlDD5rBdvl0AAFhzAa2L/08EqLUhfelfV1tF8NuxxqcLIAkpyBVBAIWap/7faiWvPi9U/FzSBUCGVjjDH1J/HYJ/aZPGjZaQJM/I68fmx9KHANUJl0yqWwfK5fNUZIf1xcfq0= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=silabs.com; spf=pass smtp.mailfrom=silabs.com; dkim=pass (2048-bit key) header.d=silabs.com header.i=@silabs.com header.b=dW7N8QpM; dkim=pass (1024-bit key) header.d=silabs.com header.i=@silabs.com header.b=KPuuLQCA; arc=fail smtp.client-ip=148.163.149.154 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=silabs.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=silabs.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=silabs.com header.i=@silabs.com header.b="dW7N8QpM"; dkim=pass (1024-bit key) header.d=silabs.com header.i=@silabs.com header.b="KPuuLQCA" Received: from pps.filterd (m0101743.ppops.net [127.0.0.1]) by mx0a-0024c301.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 61C2Lwnp2678544; Thu, 12 Feb 2026 08:44:21 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=silabs.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=pps12202023; bh=Nl0QzT7bC6vVfiXFdrOVbGV6t4ijcqbAof/+8c9ouK0=; b=dW7N8QpMl9B+ 0qrDc4JEPBAvrpFou+Ad10Ue59scplGxn7aZUuQ3LMA/yyE92gzYk0l1KAtXpi5r +56uBiG2MvQPUlFqNMKKUtvP+CEfzX+8/Rfw09lLNNSonK0MR1DOWM+F4GOTypXm gZSyXV5XayossYZ1OCW1LOc+ayqmoV18IAlSqUE0MHTdJuPJ6t8Mi80jNLpLLo7E rfI8n9eWO3BvaesZNVUl1BQgnGDTbjscfVoEJgGBkb2WytspbjdYevLunmd5dkO5 +nArWOIYtzDqJ59XmJo7V2q9NKEDQ3vbUyC2cdBmsTnv21jlpimVOC6BQUdOMwpy 5DVIYwEz0Q== Received: from dm1pr04cu001.outbound.protection.outlook.com (mail-centralusazon11020096.outbound.protection.outlook.com [52.101.61.96]) by mx0a-0024c301.pphosted.com (PPS) with ESMTPS id 4c92uysn4e-12 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Thu, 12 Feb 2026 08:44:20 -0600 (CST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=sOn3KoEWUJB4dXZN/Q8BFfgJHOX6TSSR64Ivhy4J1HsVX7eve+Qy23kv+Hr2RkmxB0RmCJ78s0cmkHSc+goznX0iGCpHihmwynHfdojl8XtXM8KwhcsLuONr1WQ7OMJvZCm7yOCIFOPlBTvLpj5cIR3dqRy5HEtLcldPgEUg2lS66H9xhxYqCb1MruaA3972eXmRdVFgkIMyFrYjyrOtGFoaizoP5tCRmpLjNigMx3YLUy35/kkKfqFRQcQZsMEvVdxSLTwNwRndyJgTqrU7HsjuoCVtqS1WJNrl2declVwjUze6uEtxT4UJosCvEn68uBZINSRYJtoNBTfnw9JicQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Nl0QzT7bC6vVfiXFdrOVbGV6t4ijcqbAof/+8c9ouK0=; b=pyAo3tDqk/iKoeNaO+XDiM+fLrWyPLmApZeTR0gMOfAqJ7En2Tpkr+hMSEMg5srzlLjx9LGTpwyQ6UiBzcmpZMyYERHE0e2rS+oWEW3LiQCm/ZU24HBuspFMMHprm8UWJaQWsbSu0CX/L0FHrsf4k3vFkb1yUM880WIia/z7W10DQ1+8qCHm/CHgueEJP6MCu6sUEhb99p4NZNQqqk/kljLweGhIo43EiCEufP2PdObQ1AEkX/vQNIAmZ6jFvTB0mhlkAPNXoPBHsEwNv6VeH/Rl6taE8lxiAo/SbNJLltnjQ5QdhGPJhgZF/HXQpjzS07AzIK/pcUhFYQx3mhIM4g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=silabs.com; dmarc=pass action=none header.from=silabs.com; dkim=pass header.d=silabs.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=silabs.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Nl0QzT7bC6vVfiXFdrOVbGV6t4ijcqbAof/+8c9ouK0=; b=KPuuLQCAbPO+mkgyJqn5ZWK3VtQS25couaNjggBMXrpHVHTMr+A6hwhY0ZfUW2TRa+JV7cIZYsBMDl+dRLKyrfPO6ECCQlwatYN4yhI7joeHRqIaOhMQhgs/67mTgXoJasidJxFTvVbAjuIrA+QC9B7HL91qIwZQgqiHwGJsRck= Received: from DS0PR11MB8205.namprd11.prod.outlook.com (2603:10b6:8:162::17) by LV8PR11MB8486.namprd11.prod.outlook.com (2603:10b6:408:1e8::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9587.19; Thu, 12 Feb 2026 14:44:16 +0000 Received: from DS0PR11MB8205.namprd11.prod.outlook.com ([fe80::2de6:bc88:2af7:3583]) by DS0PR11MB8205.namprd11.prod.outlook.com ([fe80::2de6:bc88:2af7:3583%3]) with mapi id 15.20.9611.008; Thu, 12 Feb 2026 14:44:16 +0000 From: =?UTF-8?q?Damien=20Ri=C3=A9gel?= To: greybus-dev@lists.linaro.org, Johan Hovold , Alex Elder , Greg Kroah-Hartman , linux-kernel@vger.kernel.org Cc: Silicon Labs Kernel Team , Gabriel Beaulieu , =?UTF-8?q?Damien=20Ri=C3=A9gel?= Subject: [PATCH v3 14/14] greybus: cpc: add CPC SDIO host driver Date: Thu, 12 Feb 2026 09:43:52 -0500 Message-ID: <20260212144352.93043-15-damien.riegel@silabs.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260212144352.93043-1-damien.riegel@silabs.com> References: <20260212144352.93043-1-damien.riegel@silabs.com> Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: YQBPR0101CA0124.CANPRD01.PROD.OUTLOOK.COM (2603:10b6:c01:5::27) To DS0PR11MB8205.namprd11.prod.outlook.com (2603:10b6:8:162::17) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DS0PR11MB8205:EE_|LV8PR11MB8486:EE_ X-MS-Office365-Filtering-Correlation-Id: 054401f7-0da9-446d-ceee-08de6a45325a X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|52116014|376014|1800799024|38350700014; X-Microsoft-Antispam-Message-Info: =?utf-8?B?Y1VwTWRIbjQvVXNyVTQ1dGM1SzJmV2ZtTVJVTGpWWmlVRjZGMW9PS1NOeEFZ?= =?utf-8?B?V040UjF0TnlXd3orem5CTUkyMDNGbU02SCtXYzRhU293T2ZhYzFrZVVzZWVB?= =?utf-8?B?U1NwWmRib2E3TzFVQXJBQXhPTDhCelIwN2h0RGppK0EraDVGa3hHVElWUlNR?= =?utf-8?B?UXl4RW90TzNyTEpaSHNRNTBlc096eDVlbFovbkg0d2lGNnBaZVZQd0ZEeWRq?= =?utf-8?B?VFdENDdLOWFlUHUvZkJCL2hZbjk3dDBqSVpES0FPdzBwd3pmeTZGT3l0bmND?= =?utf-8?B?WElsRFVKcytRKzJmWjl5c3dFUnhiU0kzRzFzRU1aWnNjVS9FaGJCcUFGbElz?= =?utf-8?B?TjVlTFhZRmd3Vm1QUGo3L21HSUxmUU5RT0pKdys2L3JOK3EvS0FiRDRCYXEy?= =?utf-8?B?VWJIdkR4dGRpQjBiTmlldjRkeVFMNG1uLzhJZUt0dURnQjljbmtsdDJGcEZo?= =?utf-8?B?WkRmd3VvRTM4TEtCNHd6MDJzajFBeXFUZWI1WW8xd254K29HR3JxZHkyMnlQ?= =?utf-8?B?ZVJ4Sm93UXUwbWxEVVNVdmlreFJjcWk2SkhOOCtob3Jqdk9uUnhadXFvSHRu?= =?utf-8?B?VjZlTGR3NVlydWRiRHVQWUY0TFhybWRYRlE4Z3hVeGI1UzlMNVZXV29GRmJs?= =?utf-8?B?ZGtGcDJyR1d4S29BZWhhbE5oRzhrbUV4a2ltUDVjMFcycFBoQUZaWDJrRTZz?= =?utf-8?B?eWJFMVBxNXB3RHVybzA0SW9tLzFjUTVrU3hvaVRqOFFDVlAyZFZ4YjJEOVgv?= =?utf-8?B?SUIzN0UveWk4WlpvSGNtM09kVkl1K3RJamowUjZzTmFaSXgvekpuWGM3TDJG?= =?utf-8?B?N29aay9OSy9jR1luS3F5TUZkd3ZyWWhDdDQyek5sSHEzUlR4dTRNTDNITXM0?= =?utf-8?B?SkpVcVh1ZmdWeXFLU09qNnVQYjBpbmUxdXdVbkNYdFN6L0J1anpEWk5MTDVj?= =?utf-8?B?T0pOWjJyQU5QMU9FV2xkcGUwWTZheVpLeXNoZ3pkUUtiTnFOSnVOUTRVWUtD?= =?utf-8?B?S1FPWXJ4Qk9zVmRYVGhVekw1ZkoxQTV2bGhYY1EyNkZHRXEyOENwVnM3TFkw?= =?utf-8?B?SjFBYXd6eDlRT2t4ZlZ6VWRDV1NCbmFCeHNYV1JYVkRzR3BnQVRxK3lFeGkw?= =?utf-8?B?S094b0IrSE0vQlZPZkRtRkJ1d1U3ZHlWSlVKL0s1M2Y1V0toeUZMV0xmNzU2?= =?utf-8?B?aGJONW9OSkVRaXQyVVZ4RVUyQnhBOVROa0UwcXZyaUpuZ1U1SWpxWjZyV2l4?= =?utf-8?B?alVWTFZkTG11ZjR6MXdnQ3BOWU5MQWtoQjFXZkIzQjNVLytlUGtpYTdpbXdh?= =?utf-8?B?dzRjTFJybGozMW9XYy9CVnhEVlAwS0JQakI5Y1ZXemVldVI5b1NCckVyWHFE?= =?utf-8?B?ZHBOWDdidDg3S0J3Nk5nWUhhMkV6SXVHVDUyL0wxeDFnUWlwYmNTMUFkc2JD?= =?utf-8?B?aTZiSjE2L0NEcXk5TlB3bHAzQmxGVSt0MlBFcWhYTlRMSVluTzFUcUE4RjN0?= =?utf-8?B?VTduM3pzcmFhVHRBbkFHaE1LSCtIVFkwTmdGbElzOUcrVUs1S25RTWEza2cx?= =?utf-8?B?dTF6Uy9ldlQ0a200bEdma09VT2ZnUHlBMFhuU1BzeXY1ZWlINjByemtpVHJa?= =?utf-8?B?bHBTSG5udW1Ha2N0bEEyYUFiVjZPZDFYOUcyMm9SRmlQdkFrOHI1dXgzNkNq?= =?utf-8?B?ejJDRmd0QVVQMWNxaWI0VFJ3WmlFU05QamNKUWtoclZzcEJyWHlmV1FsaGZT?= =?utf-8?B?bmQrdld0VnIvUjQ5UjhMbS9oYXhqRUFndDJyUWJlTmV2MElReWxTUWxXbXlS?= =?utf-8?B?TGdKRG43NFhRTGhObjNRaVdDNUtYU244WElHa2xqSzZVNExYSm9QNTIrVHJr?= =?utf-8?B?UW9NWGVZQjh4dkZNdnE3TWZTc3FpQytEbG1TZ3kyVWd1WnZyeG9Bb0FEZ3lF?= =?utf-8?B?NFFtc09mUVZ5Smp4UndRN1A0RnVjRVA3Z1NraXBvQXZRcG94MkRWcXpBZkE3?= =?utf-8?B?dmdRVWxRdnM2UzVSSGxleUFrTWdtZDNjc2tKbHppRFY3OTdzeHI4U0EvQ0Zl?= =?utf-8?B?Z0N0QVM1ZXZ5ZmkzSEFWS1FZKyt3bFcrV3ZBYkZUZmJCMHpKQldxc0JkbFhM?= =?utf-8?B?VlJpOExhTVJ0R3pjNVRrY05hVGJBejJLMFN2NVp2VVE3NG5DVXVERnM5SWRO?= =?utf-8?Q?0F2/wu6CiUAA4SeitGIywH8=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DS0PR11MB8205.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(52116014)(376014)(1800799024)(38350700014);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?ZjdqZUZISU9TN1VFdzAwOFdTcllzajl2dU5BcVlrYllBVEk4VzVSV0QwSCtI?= =?utf-8?B?VWpKTFlQTVpTeVFUQ1NvbDdnUWJjR2t6ZHFJMlhhL1hscGQ3WURkdUhqeko3?= =?utf-8?B?UDRvREJuZlZhUlg3U1RpRUc3L3I1MzZoa29EYkZHMW9rd216WG1hbERkbzdR?= =?utf-8?B?eHo3OFNiVUlzMmt6M2pTc0IvM0hydFdEMVNMaDFxWDNReGVpVjMzTERPaytL?= =?utf-8?B?dnZON1U0eE54bzQwODR4L3VlSS9vOEVhckdmSWpzUlRGeDZXRlR2d1ZWNjFh?= =?utf-8?B?VWtuSG1qamZRbHFQekVhNHNFRklaNWp1SGwyZzNSZnNLUW1NOE9EOXlRUmlI?= =?utf-8?B?K2h2UnU4YU9hOFoyZlpIQ2hhdC8wNTF0SmsreHFZOVRhYVlxVTJXT1VFcTVM?= =?utf-8?B?eVBlUkRGVktHRVFEYkZmMENqc3NhOXhqOG1mZlZsVHRudHd3RmxXNkJrSTZq?= =?utf-8?B?MEhIdUxGdlV6TE8rbGF4UVhmTHhIYUo1UW1HZVJvdG5QYWZNUHVadlk0WVFk?= =?utf-8?B?RzBEbDRrQlRYUXN0NEdtOG5vdkhCQTdLbEFqdTJiMUQya21neDdQd0FkUGFx?= =?utf-8?B?ZFF1UlJsaC9UMC9XRTN6VzZ4bkpFY2RNSkI1U3UrMC9lT0VkZDVNSElhZ0hU?= =?utf-8?B?WENRV1lDc3kyZjZpRmxQM2ZtTUlQdUtIOElEaUEyZnhhUTlWUmlyaW8yZlVw?= =?utf-8?B?UWdWVUVTcUVjYlBndnJFeUZCZmh2U0VSOC83Y0ZmMndrS1Bmckx1aEp0QUlN?= =?utf-8?B?Q0dOT1hWUDBScEJxejdQZzVxby9vMm5kU2pSU2lSNnFiTEFzUFhUTCtaRlA5?= =?utf-8?B?WThFZzhaLzl5U25IY0dkMlVOSHFsdWNKVnZnWXpURFVVN1h3NHdEa1VKdHdT?= =?utf-8?B?MUFtbVlzZ2lrTkoxdytwcmFtcHpZUU5XTEgwSU44MkY5a0draE1lN0xiM0dG?= =?utf-8?B?L05mcnBmb21YRjYwMWI3UkxEVStaWStYUTVyWVpvaUhDeUM5RkNWSEVQRkZ2?= =?utf-8?B?ZE9RenNnem1OaUhyZ0VTN2NHY1dPUnQ2dVJQSHFTQUtYWWlWa3Vqc1pFYUxR?= =?utf-8?B?MDFQa0dhU1l3VVBtZHZGZ3REOHdiVHZGWnplY2xGdzVZVElsVlk5ZUVMVWQ5?= =?utf-8?B?MGR4M0ZKbkJwcFZIV002NG5VeDBIVXdlQzRsOFh3OUlDN04xOWNsNk9CWkVG?= =?utf-8?B?RHlydTB3WVB0RkJjTXBRVmpaeE14R05RVUZSN01ucVN6L0tjakNWcTMzNGxX?= =?utf-8?B?SG5udmtrNlhPTnVzcHArTVI4U1F4YkhLSDNBbENoNUxMTzdRNGluY1kycTJJ?= =?utf-8?B?eXpZRisvZHNjQXBwUFNwUzB6NDlreE5PV1UyWVIvVTFtK1pHS0ZhRDJEN1Nm?= =?utf-8?B?ZWQvMkRnMmFnSUJwY25JRTJXYUtKSjVBc0lrOUdnNjBWWE85ZWl1b1FjUmRL?= =?utf-8?B?ckdsZ0tKajhudndxS2JVcDk1emxpanBGQTczYy9yK3piaEVRU1NMaUVQQkJn?= =?utf-8?B?YVZ1Q2FBK0FVVmZWenNUR3Vwc0tSUGlkVUNEdVBEZXNYbFBYbzYwSEs2SStY?= =?utf-8?B?VG01c2xxeDRHa0RURGF0S0drdmQvV3dqRkFnK21WUVFyVjJONkpyNGhGN2dr?= =?utf-8?B?UytnYmpMRzNoRWk2K2dMcTNVOGZYMXBCZTdlOGtzdE82Qnd0N3l6c3dZanhG?= =?utf-8?B?Z2RWOEVudTNhMDd0eTJuK1ZjQ09pWVZsTldUd3hWWFdSOVZCSFUwNEh1Rm4r?= =?utf-8?B?Wm5ZTE9tRHRIVjVxdEdUbmlXNDlZeHdaTE9aUVhvY2hJbXZ2ZDQwRDZCU1JF?= =?utf-8?B?a1Z4SHZHelRKbjc2V3Rva1JCQUpQakpWaWxjTFk2TkdUME4xb1BQYkpWM0F1?= =?utf-8?B?OUI3aE13WE52T0NxRFg3R0tXYTV6Z0FlbmpVYnlMTVorOXYrR0JRNFdLK1NT?= =?utf-8?B?Rzc4OEVTWFJiMUFUMU9lMStZd0IvL0x6WkZSSG9ML3RsYjhZUExvSXo2ZFNh?= =?utf-8?B?SVhnQzBQSE9nZ3RlSzJOMFhuOWozTnRxOHRONzF3TzZXenJ0QXpydHlSL0xM?= =?utf-8?B?dFBlVW5KQ0h3Y0o5SXhSakZWdWpUMG91YTdBamxoWkVwQU93K1VORkt0M09m?= =?utf-8?B?VHVvRW50RGNQSUZ4QmlPWkhqczlucXorUEhybEpOL0hUaS9wcmRNeDIzeVhi?= =?utf-8?B?SnIrTU5ZaE5sZ2ZLUGtrbmx3eThDcXdmbXQ0WTFkZkNaNDB6WXMydzI5WVc2?= =?utf-8?B?cWszOU5QVWpsRXVHclZ2V3JJcUxDRnNMelhwTldEdnJzR0NHUFRHZ2VpT2w2?= =?utf-8?B?YnB4QWZqdEVsQXlxNTQwOFVENHlmd1VNTmZCUFNzRWFnNlR2MUQvdz09?= X-OriginatorOrg: silabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: 054401f7-0da9-446d-ceee-08de6a45325a X-MS-Exchange-CrossTenant-AuthSource: DS0PR11MB8205.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Feb 2026 14:44:16.4743 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 54dbd822-5231-4b20-944d-6f4abcd541fb X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: knNGmAGPzQf25G3ADfz92TnQsQI/dvgnqBOWJWpLNw4B+KjuVjbGvyqsMHWZ9hXcNOE5OQdxrm6Tn6NewRibNw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LV8PR11MB8486 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjEyMDExMSBTYWx0ZWRfX34qT7oqqMXAo Hxsdk4J22E9fovRDACG8nsX1MrrBTF6JANgL5ZdE6mz5BHvooT71hCRLT1yIuApJ0w5a1DLVIZB Lb03Ls323u/1HpEBIBuMUEfEu7SKXQjL/eu5F9LG97ofarm77f2jGv7yBnoEX7Dt+CMTZbxVV3q FTZgkwCLsV761MOabTyXFJ07LZgm/10mmNKjGCskvzVTY4zpZFPyTgdT8dUEulcn4cSAvsRZuoS 9UGj3hlrA7CqMfcO73Ejp26+YRoekxZg71DDfGvBFr8/p7ccK450pIfbpatOkT0DOqMI0S3+gRM coLvvo95WUQWayQwleSJEqTVrMZLvmG5rTePD2gSkIFaAeQ2Z+n4RkPzJ4xOsSlPjc7NqcbeNjQ JwU+jum8CnWj0JhDSazc3OzjAibaaZowimzpfCwZyptOd6gpmBQVmwqVIJmoBbq+0xNT1XH3mOV SSZMAPftZwtyC0vMytQ== X-Authority-Analysis: v=2.4 cv=DtRbOW/+ c=1 sm=1 tr=0 ts=698de745 cx=c_pps a=TvliyZNEFSK35vtP2Nadqg==:117 a=6eWqkTHjU83fiwn7nKZWdM+Sl24=:19 a=z/mQ4Ysz8XfWz/Q5cLBRGdckG28=:19 a=lCpzRmAYbLLaTzLvsPZ7Mbvzbb8=:19 a=xqWC_Br6kY4A:10 a=IkcTkHD0fZMA:10 a=HzLeVaNsDn8A:10 a=M51BFTxLslgA:10 a=i1IsUcr2s-wA:10 a=VkNPw1HP01LnGYTKEx00:22 a=Mpw57Om8IfrbqaoTuvik:22 a=GgsMoib0sEa3-_RKJdDe:22 a=2AEO0YjSAAAA:8 a=d9NkVR4ycPgQUKVUYPAA:9 a=3ZKOabzyN94A:10 a=QEXdDO2ut3YA:10 X-Proofpoint-ORIG-GUID: KYhDRgtOKiVdW8uOWIQNkmyYfVWgGmfE X-Proofpoint-GUID: KYhDRgtOKiVdW8uOWIQNkmyYfVWgGmfE X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.51,FMLib:17.12.100.49 definitions=2026-02-12_04,2026-02-12_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 suspectscore=0 spamscore=0 impostorscore=0 lowpriorityscore=0 bulkscore=0 clxscore=1015 malwarescore=0 adultscore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2601150000 definitions=main-2602120111 From: Gabriel Beaulieu This introduces a new module gb-cpc-sdio, in order to communicate with a Greybus CPC device over SDIO. Most of the complexity stems from aggregation: packets are aggregated to minimize the number of CMD53s. In the first block, the first le32 is the number of packets in this transfer. Immediately after that are all the packet headers (CPC + Greybus). This lets the device process all the headers in a single interrupt, and prepare the ADMA descriptors for all the payloads in one go. Payloads start at the beginning of the second block and are concatained. Their lengths must be 32-bit aligned, so the driver takes care of adding and removing padding if necessary. Signed-off-by: Gabriel Beaulieu Signed-off-by: Damien Ri=C3=A9gel --- Changes in v3: - rework defines to group together address-related defines and remove orphaned value - remove trivial comments - all RX and TX are now done from the workqueue. In previous iterations, transfers could either be done from the threaded IRQ or from the workqueue. - remove erroneous SDIO VID/PID - remove padding between headers and payloads when aggregating Changes in v2: - change formatting from %lu to %zu when printing size_t's - remove "/**" kernel-doc marker for static functions not actually using the kernel-doc format - reduce header inclusion list - use reverse christmas tree variable declarations consistently - update aggregation functions to try to be more legible - use define instead of constant value 0x0C for the address where to read the number of bytes the device wants to send drivers/greybus/cpc/Kconfig | 12 + drivers/greybus/cpc/Makefile | 3 + drivers/greybus/cpc/sdio.c | 480 +++++++++++++++++++++++++++++++++++ 3 files changed, 495 insertions(+) create mode 100644 drivers/greybus/cpc/sdio.c diff --git a/drivers/greybus/cpc/Kconfig b/drivers/greybus/cpc/Kconfig index 0e72383381a..50f4c27666d 100644 --- a/drivers/greybus/cpc/Kconfig +++ b/drivers/greybus/cpc/Kconfig @@ -10,3 +10,15 @@ config GREYBUS_CPC =20 To compile this code as a module, chose M here: the module will be called gb-cpc.ko + +config GREYBUS_CPC_SDIO + tristate "Greybus CPC over SDIO" + depends on GREYBUS_CPC && MMC + help + This driver provides Greybus CPC host support for devices + connected via SDIO interface. + + To compile this driver as a module, choose M here: the module + will be called gb-cpc-sdio. + + If unsure, say N. diff --git a/drivers/greybus/cpc/Makefile b/drivers/greybus/cpc/Makefile index c4b530d27a3..3296536e86d 100644 --- a/drivers/greybus/cpc/Makefile +++ b/drivers/greybus/cpc/Makefile @@ -4,3 +4,6 @@ gb-cpc-y :=3D cport.o header.o host.o protocol.o =20 # CPC core obj-$(CONFIG_GREYBUS_CPC) +=3D gb-cpc.o + +gb-cpc-sdio-y :=3D sdio.o +obj-$(CONFIG_GREYBUS_CPC_SDIO) +=3D gb-cpc-sdio.o diff --git a/drivers/greybus/cpc/sdio.c b/drivers/greybus/cpc/sdio.c new file mode 100644 index 00000000000..34dfa7c1db1 --- /dev/null +++ b/drivers/greybus/cpc/sdio.c @@ -0,0 +1,480 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2025, Silicon Laboratories, Inc. + */ + +#include +#include +#include +#include +#include + +#include "cpc.h" +#include "header.h" +#include "host.h" + +#define GB_CPC_SDIO_MSG_SIZE_MAX 4096 +#define GB_CPC_SDIO_BLOCK_SIZE 256 +#define GB_CPC_SDIO_ALIGNMENT 4 +#define CPC_FRAME_HEADER_SIZE (sizeof(struct cpc_header) + sizeof(struct g= b_operation_msg_hdr)) + +#define GB_CPC_SDIO_ADDR_FIFO 0x00 +#define GB_CPC_SDIO_ADDR_RX_BYTES_CNT 0x0C + +enum cpc_sdio_flags { + CPC_SDIO_FLAG_RX_PENDING, + CPC_SDIO_FLAG_SHUTDOWN, +}; + +struct cpc_sdio { + struct cpc_host_device *cpc_hd; + struct device *dev; + struct sdio_func *func; + + struct work_struct rxtx_work; + unsigned long flags; + + wait_queue_head_t event_queue; + u8 max_aggregation; +}; + +struct frame_header { + struct cpc_header cpc; + struct gb_operation_msg_hdr gb; +} __packed; + +static inline struct cpc_sdio *cpc_hd_to_cpc_sdio(struct cpc_host_device *= cpc_hd) +{ + return (struct cpc_sdio *)cpc_hd->priv; +} + +static int gb_cpc_sdio_wake_tx(struct cpc_host_device *cpc_hd) +{ + struct cpc_sdio *ctx =3D cpc_hd_to_cpc_sdio(cpc_hd); + + if (test_bit(CPC_SDIO_FLAG_SHUTDOWN, &ctx->flags)) + return 0; + + schedule_work(&ctx->rxtx_work); + + return 0; +} + +/* + * Return the memory requirement in bytes for the aggregated frame aligned= to the block size. + * All headers are contained in a dedicated block. Then payloads start at = the beginning of second + * block. Each individual payload must be 4-byte aligned, and the total mu= st be block-aligned. + */ +static size_t cpc_sdio_get_aligned_size(struct cpc_sdio *ctx, struct sk_bu= ff_head *frame_list) +{ + struct sk_buff *frame; + size_t size =3D 0; + + skb_queue_walk(frame_list, frame) + size +=3D ALIGN(frame->len, GB_CPC_SDIO_ALIGNMENT); + + size =3D ALIGN(size, GB_CPC_SDIO_BLOCK_SIZE); + + return size; +} + +static size_t cpc_sdio_build_aggregated_frame(struct cpc_sdio *ctx, + struct sk_buff_head *frame_list, + unsigned char **buffer) +{ + unsigned char *tx_buff; + struct sk_buff *frame; + __le32 *frame_count; + size_t xfer_size; + unsigned int i =3D 0; + + xfer_size =3D cpc_sdio_get_aligned_size(ctx, frame_list); + + tx_buff =3D kmalloc(xfer_size, GFP_KERNEL); + if (!tx_buff) + return 0; + + frame_count =3D (__le32 *)tx_buff; + *frame_count =3D cpu_to_le32(skb_queue_len(frame_list)); + i +=3D sizeof(*frame_count); + + /* First step is to aggregate all headers together */ + skb_queue_walk(frame_list, frame) { + struct frame_header *fh =3D (struct frame_header *)&tx_buff[i]; + + memcpy(fh, frame->data, sizeof(*fh)); + i +=3D sizeof(*fh); + } + + skb_queue_walk(frame_list, frame) { + size_t payload_len, padding_len; + + if (frame->len <=3D CPC_FRAME_HEADER_SIZE) + continue; + + payload_len =3D frame->len - CPC_FRAME_HEADER_SIZE; + memcpy(&tx_buff[i], &frame->data[CPC_FRAME_HEADER_SIZE], payload_len); + i +=3D payload_len; + + padding_len =3D ALIGN(payload_len, GB_CPC_SDIO_ALIGNMENT) - payload_len; + if (padding_len) { + memset(&tx_buff[i], 0, padding_len); + i +=3D padding_len; + } + } + + *buffer =3D tx_buff; + + return xfer_size; +} + +static bool cpc_sdio_get_payload_size(struct cpc_sdio *ctx, const struct f= rame_header *header, + size_t *payload_size) +{ + size_t gb_size; + + gb_size =3D le16_to_cpu(header->gb.size); + + if (gb_size < sizeof(header->gb)) { + dev_dbg(ctx->dev, "Invalid Greybus header size: %zu\n", gb_size); + return false; + } + + if (gb_size > (GB_CPC_SDIO_MSG_SIZE_MAX + sizeof(header->gb))) { + dev_dbg(ctx->dev, "Payload size exceeds maximum: %zu\n", gb_size); + return false; + } + + *payload_size =3D gb_size - sizeof(header->gb); + + return true; +} + +/* + * Process aggregated frame + * Reconstructed frame layout: + * +-----+-----+-----+------+------+------+------+-------+---------+ + * | CPC Header (4B) | Size | OpID | Type | Stat | CPort | Payload | + * +-----+-----+-----+------+------+------+------+-------+---------+ + */ +static void cpc_sdio_process_aggregated_frame(struct cpc_sdio *ctx, unsign= ed char *aggregated_frame, + unsigned int frame_len) +{ + const unsigned char *payload_start; + const struct frame_header *header; + unsigned int payload_offset; + size_t aligned_payload_size; + struct sk_buff *rx_skb; + __le32 frame_count_le; + size_t payload_size; + size_t frame_size; + u32 frame_count; + + frame_count_le =3D *((__le32 *)aggregated_frame); + frame_count =3D le32_to_cpu(frame_count_le); + + if (frame_count > ctx->max_aggregation) { + dev_warn(ctx->dev, + "Process aggregated frame: frame count %u exceeds negotiated maximum %= u\n", + frame_count, ctx->max_aggregation); + return; + } + + /* Header starts at block 0 after frame count */ + header =3D (struct frame_header *)&aggregated_frame[sizeof(frame_count_le= )]; + + /* Payloads start at block 1 (after complete block 0) */ + payload_offset =3D (frame_count * CPC_FRAME_HEADER_SIZE) + sizeof(frame_c= ount_le); + + for (unsigned int i =3D 0; i < frame_count; i++) { + payload_start =3D &aggregated_frame[payload_offset]; + + if (!cpc_sdio_get_payload_size(ctx, header, &payload_size)) { + dev_err(ctx->dev, + "Process aggregated frame: failed to get payload size, aborting.\n"); + return; + } + + aligned_payload_size =3D ALIGN(payload_size, GB_CPC_SDIO_ALIGNMENT); + + if (payload_offset + aligned_payload_size > frame_len) { + dev_err(ctx->dev, + "Process aggregated frame: payload is out of buffer boundary, aborting= at frame %u\n", + i); + return; + } + + frame_size =3D CPC_FRAME_HEADER_SIZE + payload_size; + + rx_skb =3D alloc_skb(frame_size, GFP_KERNEL); + if (!rx_skb) + return; + + memcpy(skb_put(rx_skb, CPC_FRAME_HEADER_SIZE), header, CPC_FRAME_HEADER_= SIZE); + + if (payload_size > 0) + memcpy(skb_put(rx_skb, payload_size), payload_start, payload_size); + + cpc_hd_rcvd(ctx->cpc_hd, rx_skb); + + header++; + payload_offset +=3D aligned_payload_size; + } +} + +static u32 cpc_sdio_get_rx_num_bytes(struct sdio_func *func, int *err) +{ + unsigned int rx_num_block_addr =3D GB_CPC_SDIO_ADDR_RX_BYTES_CNT; + + return sdio_readl(func, rx_num_block_addr, err); +} + +static void gb_cpc_sdio_rx(struct cpc_sdio *ctx) +{ + unsigned char *rx_buff; + size_t data_len; + int err; + + sdio_claim_host(ctx->func); + data_len =3D cpc_sdio_get_rx_num_bytes(ctx->func, &err); + + if (err) { + dev_err(ctx->dev, "failed to obtain byte count (%d)\n", err); + goto release_host; + } + + if (data_len < sizeof(u32) + CPC_FRAME_HEADER_SIZE) { + dev_err(ctx->dev, "failed to obtain enough bytes for a header (%zu)\n", = data_len); + goto release_host; + } + + rx_buff =3D kmalloc(data_len, GFP_KERNEL); + if (!rx_buff) + goto release_host; + + err =3D sdio_readsb(ctx->func, rx_buff, GB_CPC_SDIO_ADDR_FIFO, data_len); + sdio_release_host(ctx->func); + + if (err) { + dev_err(ctx->dev, "failed to sdio_readsb (%d)\n", err); + goto free_rx_skb; + } + + if (data_len < GB_CPC_SDIO_BLOCK_SIZE) { + dev_err(ctx->dev, "received %zd bytes, expected at least %u bytes\n", da= ta_len, + GB_CPC_SDIO_BLOCK_SIZE); + goto free_rx_skb; + } + + cpc_sdio_process_aggregated_frame(ctx, rx_buff, data_len); + +free_rx_skb: + kfree(rx_buff); + + return; + +release_host: + sdio_release_host(ctx->func); +} + +static int gb_cpc_sdio_tx(struct cpc_sdio *ctx) +{ + struct sk_buff_head frame_list; + unsigned char *tx_buff; + size_t tx_len; + int pkt_sent; + int err; + + skb_queue_head_init(&frame_list); + + cpc_hd_dequeue_many(ctx->cpc_hd, &frame_list, ctx->max_aggregation); + + if (skb_queue_empty(&frame_list)) + return 0; + + tx_len =3D cpc_sdio_build_aggregated_frame(ctx, &frame_list, &tx_buff); + if (!tx_len) { + dev_err(ctx->dev, "failed to build aggregated frame\n"); + goto cleanup_frames; + } + + sdio_claim_host(ctx->func); + err =3D sdio_writesb(ctx->func, GB_CPC_SDIO_ADDR_FIFO, tx_buff, tx_len); + sdio_release_host(ctx->func); + + kfree(tx_buff); + +cleanup_frames: + pkt_sent =3D skb_queue_len(&frame_list); + skb_queue_purge(&frame_list); + + return pkt_sent; +} + +static void gb_cpc_sdio_rxtx_work(struct work_struct *work) +{ + struct cpc_sdio *ctx =3D container_of(work, struct cpc_sdio, rxtx_work); + int num_tx =3D 0; + + do { + if (test_and_clear_bit(CPC_SDIO_FLAG_RX_PENDING, &ctx->flags)) + gb_cpc_sdio_rx(ctx); + + num_tx =3D gb_cpc_sdio_tx(ctx); + } while (num_tx); +} + +static struct cpc_hd_driver cpc_sdio_driver =3D { + .wake_tx =3D gb_cpc_sdio_wake_tx, +}; + +static int cpc_sdio_init(struct sdio_func *func) +{ + unsigned char rx_data_ready_irq_en_bit =3D BIT(0); + unsigned int irq_enable_addr =3D 0x09; + int err; + + sdio_writeb(func, rx_data_ready_irq_en_bit, irq_enable_addr, &err); + + return err; +} + +static void cpc_sdio_irq_handler(struct sdio_func *func) +{ + unsigned int rx_data_pending_irq_bit =3D 0; + unsigned int irq_status_addr =3D 0x08; + unsigned long int_status; + struct cpc_sdio *ctx; + struct device *dev; + int err; + + ctx =3D sdio_get_drvdata(func); + dev =3D &func->dev; + + int_status =3D sdio_readb(func, irq_status_addr, &err); + if (err) + return; + + if (__test_and_clear_bit(rx_data_pending_irq_bit, &int_status)) { + sdio_writeb(func, BIT(rx_data_pending_irq_bit), irq_status_addr, &err); + if (err) + return; + + set_bit(CPC_SDIO_FLAG_RX_PENDING, &ctx->flags); + schedule_work(&ctx->rxtx_work); + } + + if (int_status) + dev_err_once(dev, "unhandled interrupt from the device (%ld)\n", int_sta= tus); +} + +static int cpc_sdio_probe(struct sdio_func *func, const struct sdio_device= _id *id) +{ + struct cpc_host_device *cpc_hd; + struct cpc_sdio *ctx; + int err; + + ctx =3D kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + cpc_hd =3D cpc_hd_create(&cpc_sdio_driver, &func->dev, ctx); + if (IS_ERR(cpc_hd)) { + kfree(ctx); + return PTR_ERR(cpc_hd); + } + + ctx->cpc_hd =3D cpc_hd; + ctx->dev =3D cpc_hd_dev(cpc_hd); + ctx->func =3D func; + ctx->max_aggregation =3D 1; + + INIT_WORK(&ctx->rxtx_work, gb_cpc_sdio_rxtx_work); + + sdio_set_drvdata(func, ctx); + + sdio_claim_host(func); + + err =3D sdio_enable_func(func); + if (err) + goto release_host; + + err =3D sdio_set_block_size(func, GB_CPC_SDIO_BLOCK_SIZE); + if (err) + goto disable_func; + + err =3D cpc_sdio_init(func); + if (err) + goto disable_func; + + err =3D sdio_claim_irq(func, cpc_sdio_irq_handler); + if (err) + goto disable_func; + + err =3D cpc_hd_add(cpc_hd); + if (err) + goto release_irq; + + sdio_release_host(func); + + return 0; + +release_irq: + sdio_release_irq(func); + +disable_func: + sdio_disable_func(func); + +release_host: + sdio_release_host(func); + cpc_hd_put(cpc_hd); + kfree(ctx); + + return err; +} + +static void cpc_sdio_remove(struct sdio_func *func) +{ + struct cpc_sdio *ctx =3D sdio_get_drvdata(func); + struct cpc_host_device *cpc_hd =3D ctx->cpc_hd; + + set_bit(CPC_SDIO_FLAG_SHUTDOWN, &ctx->flags); + + + sdio_claim_host(func); + sdio_release_irq(func); + + cancel_work_sync(&ctx->rxtx_work); + + sdio_disable_func(func); + sdio_release_host(func); + + cpc_hd_del(cpc_hd); + cpc_hd_put(cpc_hd); + + kfree(ctx); +} + +static const struct sdio_device_id sdio_ids[] =3D { + /* No official ID */ + { SDIO_DEVICE(0x0000, 0x1000), }, + { }, +}; +MODULE_DEVICE_TABLE(sdio, sdio_ids); + +static struct sdio_driver gb_cpc_sdio_driver =3D { + .name =3D KBUILD_MODNAME, + .id_table =3D sdio_ids, + .probe =3D cpc_sdio_probe, + .remove =3D cpc_sdio_remove, + .drv =3D { + .owner =3D THIS_MODULE, + .name =3D KBUILD_MODNAME, + }, +}; + +module_sdio_driver(gb_cpc_sdio_driver); + +MODULE_DESCRIPTION("Greybus Host Driver for Silicon Labs devices using SDI= O"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Damien Ri=C3=A9gel "); --=20 2.52.0