1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * AMD MP2 PCIe communication driver 4 * Copyright 2020-2021 Advanced Micro Devices, Inc. 5 * 6 * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> 7 * Sandeep Singh <Sandeep.singh@amd.com> 8 * Basavaraj Natikar <Basavaraj.Natikar@amd.com> 9 */ 10 11 #include <linux/bitops.h> 12 #include <linux/delay.h> 13 #include <linux/devm-helpers.h> 14 #include <linux/dma-mapping.h> 15 #include <linux/dmi.h> 16 #include <linux/interrupt.h> 17 #include <linux/io-64-nonatomic-lo-hi.h> 18 #include <linux/iopoll.h> 19 #include <linux/module.h> 20 #include <linux/slab.h> 21 #include <linux/string_choices.h> 22 23 #include "amd_sfh_pcie.h" 24 #include "sfh1_1/amd_sfh_init.h" 25 26 #define DRIVER_NAME "pcie_mp2_amd" 27 #define DRIVER_DESC "AMD(R) PCIe MP2 Communication Driver" 28 29 #define ACEL_EN BIT(0) 30 #define GYRO_EN BIT(1) 31 #define MAGNO_EN BIT(2) 32 #define OP_EN BIT(15) 33 #define HPD_EN BIT(16) 34 #define ALS_EN BIT(19) 35 #define ACS_EN BIT(22) 36 37 static int sensor_mask_override = -1; 38 module_param_named(sensor_mask, sensor_mask_override, int, 0444); 39 MODULE_PARM_DESC(sensor_mask, "override the detected sensors mask"); 40 41 static bool intr_disable = true; 42 43 static int amd_sfh_wait_response_v2(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts) 44 { 45 union cmd_response cmd_resp; 46 47 /* Get response with status within a max of 10 seconds timeout */ 48 if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG(0), cmd_resp.resp, 49 (cmd_resp.response_v2.response == sensor_sts && 50 cmd_resp.response_v2.status == 0 && (sid == 0xff || 51 cmd_resp.response_v2.sensor_id == sid)), 500, 10000000)) 52 return cmd_resp.response_v2.response; 53 54 return SENSOR_DISABLED; 55 } 56 57 static void amd_start_sensor_v2(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info) 58 { 59 union sfh_cmd_base cmd_base; 60 61 cmd_base.ul = 0; 62 cmd_base.cmd_v2.cmd_id = ENABLE_SENSOR; 63 cmd_base.cmd_v2.intr_disable = intr_disable; 64 cmd_base.cmd_v2.period = info.period; 65 cmd_base.cmd_v2.sensor_id = info.sensor_idx; 66 cmd_base.cmd_v2.length = 16; 67 68 if (info.sensor_idx == als_idx) 69 cmd_base.cmd_v2.mem_type = USE_C2P_REG; 70 71 writeq(info.dma_address, privdata->mmio + AMD_C2P_MSG1); 72 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); 73 } 74 75 static void amd_stop_sensor_v2(struct amd_mp2_dev *privdata, u16 sensor_idx) 76 { 77 union sfh_cmd_base cmd_base; 78 79 cmd_base.ul = 0; 80 cmd_base.cmd_v2.cmd_id = DISABLE_SENSOR; 81 cmd_base.cmd_v2.intr_disable = intr_disable; 82 cmd_base.cmd_v2.period = 0; 83 cmd_base.cmd_v2.sensor_id = sensor_idx; 84 cmd_base.cmd_v2.length = 16; 85 86 writeq(0x0, privdata->mmio + AMD_C2P_MSG1); 87 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); 88 } 89 90 static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata) 91 { 92 union sfh_cmd_base cmd_base; 93 94 cmd_base.cmd_v2.cmd_id = STOP_ALL_SENSORS; 95 cmd_base.cmd_v2.intr_disable = intr_disable; 96 cmd_base.cmd_v2.period = 0; 97 cmd_base.cmd_v2.sensor_id = 0; 98 99 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); 100 } 101 102 void amd_sfh_clear_intr_v2(struct amd_mp2_dev *privdata) 103 { 104 if (readl(privdata->mmio + amd_get_p2c_val(privdata, 4))) { 105 writel(0, privdata->mmio + amd_get_p2c_val(privdata, 4)); 106 writel(0xf, privdata->mmio + amd_get_p2c_val(privdata, 5)); 107 } 108 } 109 110 void amd_sfh_clear_intr(struct amd_mp2_dev *privdata) 111 { 112 if (privdata->mp2_ops->clear_intr) 113 privdata->mp2_ops->clear_intr(privdata); 114 } 115 116 static irqreturn_t amd_sfh_irq_handler(int irq, void *data) 117 { 118 amd_sfh_clear_intr(data); 119 120 return IRQ_HANDLED; 121 } 122 123 int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata) 124 { 125 int rc; 126 127 pcim_intx(privdata->pdev, true); 128 129 rc = devm_request_irq(&privdata->pdev->dev, privdata->pdev->irq, 130 amd_sfh_irq_handler, 0, DRIVER_NAME, privdata); 131 if (rc) { 132 dev_err(&privdata->pdev->dev, "failed to request irq %d err=%d\n", 133 privdata->pdev->irq, rc); 134 return rc; 135 } 136 137 return 0; 138 } 139 140 static int amd_sfh_dis_sts_v2(struct amd_mp2_dev *privdata) 141 { 142 return (readl(privdata->mmio + AMD_P2C_MSG(1)) & 143 SENSOR_DISCOVERY_STATUS_MASK) >> SENSOR_DISCOVERY_STATUS_SHIFT; 144 } 145 146 static void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info) 147 { 148 union sfh_cmd_param cmd_param; 149 union sfh_cmd_base cmd_base; 150 151 /* fill up command register */ 152 memset(&cmd_base, 0, sizeof(cmd_base)); 153 cmd_base.s.cmd_id = ENABLE_SENSOR; 154 cmd_base.s.period = info.period; 155 cmd_base.s.sensor_id = info.sensor_idx; 156 157 /* fill up command param register */ 158 memset(&cmd_param, 0, sizeof(cmd_param)); 159 cmd_param.s.buf_layout = 1; 160 cmd_param.s.buf_length = 16; 161 162 writeq(info.dma_address, privdata->mmio + AMD_C2P_MSG2); 163 writel(cmd_param.ul, privdata->mmio + AMD_C2P_MSG1); 164 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); 165 } 166 167 static void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx) 168 { 169 union sfh_cmd_base cmd_base; 170 171 /* fill up command register */ 172 memset(&cmd_base, 0, sizeof(cmd_base)); 173 cmd_base.s.cmd_id = DISABLE_SENSOR; 174 cmd_base.s.period = 0; 175 cmd_base.s.sensor_id = sensor_idx; 176 177 writeq(0x0, privdata->mmio + AMD_C2P_MSG2); 178 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); 179 } 180 181 static void amd_stop_all_sensors(struct amd_mp2_dev *privdata) 182 { 183 union sfh_cmd_base cmd_base; 184 185 /* fill up command register */ 186 memset(&cmd_base, 0, sizeof(cmd_base)); 187 cmd_base.s.cmd_id = STOP_ALL_SENSORS; 188 cmd_base.s.period = 0; 189 cmd_base.s.sensor_id = 0; 190 191 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); 192 } 193 194 static const struct dmi_system_id dmi_sensor_mask_overrides[] = { 195 { 196 .matches = { 197 DMI_MATCH(DMI_PRODUCT_NAME, "HP ENVY x360 Convertible 13-ag0xxx"), 198 }, 199 .driver_data = (void *)(ACEL_EN | MAGNO_EN), 200 }, 201 { 202 .matches = { 203 DMI_MATCH(DMI_PRODUCT_NAME, "HP ENVY x360 Convertible 15-cp0xxx"), 204 }, 205 .driver_data = (void *)(ACEL_EN | MAGNO_EN), 206 }, 207 { } 208 }; 209 210 int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id) 211 { 212 int activestatus, num_of_sensors = 0; 213 const struct dmi_system_id *dmi_id; 214 215 if (sensor_mask_override == -1) { 216 dmi_id = dmi_first_match(dmi_sensor_mask_overrides); 217 if (dmi_id) 218 sensor_mask_override = (long)dmi_id->driver_data; 219 } 220 221 if (sensor_mask_override >= 0) { 222 activestatus = sensor_mask_override; 223 } else { 224 activestatus = privdata->mp2_acs >> 4; 225 } 226 227 if (ACEL_EN & activestatus) 228 sensor_id[num_of_sensors++] = accel_idx; 229 230 if (GYRO_EN & activestatus) 231 sensor_id[num_of_sensors++] = gyro_idx; 232 233 if (MAGNO_EN & activestatus) 234 sensor_id[num_of_sensors++] = mag_idx; 235 236 if (OP_EN & activestatus) 237 sensor_id[num_of_sensors++] = op_idx; 238 239 if (ALS_EN & activestatus) 240 sensor_id[num_of_sensors++] = als_idx; 241 242 if (HPD_EN & activestatus) 243 sensor_id[num_of_sensors++] = HPD_IDX; 244 245 if (ACS_EN & activestatus) 246 sensor_id[num_of_sensors++] = ACS_IDX; 247 248 return num_of_sensors; 249 } 250 251 static void amd_mp2_pci_remove(void *privdata) 252 { 253 struct amd_mp2_dev *mp2 = privdata; 254 amd_sfh_hid_client_deinit(privdata); 255 mp2->mp2_ops->stop_all(mp2); 256 pcim_intx(mp2->pdev, false); 257 amd_sfh_clear_intr(mp2); 258 } 259 260 static struct amd_mp2_ops amd_sfh_ops_v2 = { 261 .start = amd_start_sensor_v2, 262 .stop = amd_stop_sensor_v2, 263 .stop_all = amd_stop_all_sensor_v2, 264 .response = amd_sfh_wait_response_v2, 265 .clear_intr = amd_sfh_clear_intr_v2, 266 .init_intr = amd_sfh_irq_init_v2, 267 .discovery_status = amd_sfh_dis_sts_v2, 268 .remove = amd_mp2_pci_remove, 269 }; 270 271 static struct amd_mp2_ops amd_sfh_ops = { 272 .start = amd_start_sensor, 273 .stop = amd_stop_sensor, 274 .stop_all = amd_stop_all_sensors, 275 .remove = amd_mp2_pci_remove, 276 }; 277 278 static void mp2_select_ops(struct amd_mp2_dev *privdata) 279 { 280 u8 acs; 281 282 privdata->mp2_acs = readl(privdata->mmio + AMD_P2C_MSG3); 283 acs = privdata->mp2_acs & GENMASK(3, 0); 284 285 switch (acs) { 286 case V2_STATUS: 287 privdata->mp2_ops = &amd_sfh_ops_v2; 288 break; 289 default: 290 privdata->mp2_ops = &amd_sfh_ops; 291 break; 292 } 293 } 294 295 int amd_sfh_irq_init(struct amd_mp2_dev *privdata) 296 { 297 if (privdata->mp2_ops->init_intr) 298 return privdata->mp2_ops->init_intr(privdata); 299 300 return 0; 301 } 302 303 static int mp2_disable_intr(const struct dmi_system_id *id) 304 { 305 intr_disable = false; 306 return 0; 307 } 308 309 static const struct dmi_system_id dmi_sfh_table[] = { 310 { 311 /* 312 * https://bugzilla.kernel.org/show_bug.cgi?id=218104 313 */ 314 .callback = mp2_disable_intr, 315 .matches = { 316 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 317 DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook x360 435 G7"), 318 }, 319 }, 320 {} 321 }; 322 323 static const struct dmi_system_id dmi_nodevs[] = { 324 { 325 /* 326 * Google Chromebooks use Chrome OS Embedded Controller Sensor 327 * Hub instead of Sensor Hub Fusion and leaves MP2 328 * uninitialized, which disables all functionalities, even 329 * including the registers necessary for feature detections. 330 */ 331 .matches = { 332 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 333 }, 334 }, 335 { } 336 }; 337 338 static ssize_t hpd_show(struct device *dev, struct device_attribute *attr, char *buf) 339 { 340 struct amd_mp2_dev *mp2 = dev_get_drvdata(dev); 341 342 return sysfs_emit(buf, "%s\n", str_enabled_disabled(mp2->dev_en.is_hpd_enabled)); 343 } 344 345 static ssize_t hpd_store(struct device *dev, 346 struct device_attribute *attr, 347 const char *buf, size_t count) 348 { 349 struct amd_mp2_dev *mp2 = dev_get_drvdata(dev); 350 bool enabled; 351 int ret; 352 353 ret = kstrtobool(buf, &enabled); 354 if (ret) 355 return ret; 356 357 mp2->sfh1_1_ops->toggle_hpd(mp2, enabled); 358 359 return count; 360 } 361 static DEVICE_ATTR_RW(hpd); 362 363 static umode_t sfh_attr_is_visible(struct kobject *kobj, struct attribute *attr, int idx) 364 { 365 struct device *dev = kobj_to_dev(kobj); 366 struct amd_mp2_dev *mp2 = dev_get_drvdata(dev); 367 368 if (!mp2->sfh1_1_ops || !mp2->dev_en.is_hpd_present) 369 return 0; 370 371 return attr->mode; 372 } 373 374 static struct attribute *sfh_attrs[] = { 375 &dev_attr_hpd.attr, 376 NULL, 377 }; 378 379 static struct attribute_group sfh_attr_group = { 380 .attrs = sfh_attrs, 381 .is_visible = sfh_attr_is_visible, 382 }; 383 384 static const struct attribute_group *amd_sfh_groups[] = { 385 &sfh_attr_group, 386 NULL, 387 }; 388 389 static void sfh1_1_init_work(struct work_struct *work) 390 { 391 struct amd_mp2_dev *mp2 = container_of(work, struct amd_mp2_dev, work); 392 int rc; 393 394 rc = mp2->sfh1_1_ops->init(mp2); 395 if (rc) 396 return; 397 398 amd_sfh_clear_intr(mp2); 399 mp2->init_done = 1; 400 401 rc = sysfs_update_group(&mp2->pdev->dev.kobj, &sfh_attr_group); 402 if (rc) 403 dev_warn(&mp2->pdev->dev, "failed to update sysfs group\n"); 404 405 } 406 407 static void sfh_init_work(struct work_struct *work) 408 { 409 struct amd_mp2_dev *mp2 = container_of(work, struct amd_mp2_dev, work); 410 struct pci_dev *pdev = mp2->pdev; 411 int rc; 412 413 rc = amd_sfh_hid_client_init(mp2); 414 if (rc) { 415 amd_sfh_clear_intr(mp2); 416 dev_err(&pdev->dev, "amd_sfh_hid_client_init failed err %d\n", rc); 417 return; 418 } 419 420 amd_sfh_clear_intr(mp2); 421 mp2->init_done = 1; 422 } 423 424 static void amd_sfh_remove(struct pci_dev *pdev) 425 { 426 struct amd_mp2_dev *mp2 = pci_get_drvdata(pdev); 427 428 flush_work(&mp2->work); 429 if (mp2->init_done) 430 mp2->mp2_ops->remove(mp2); 431 } 432 433 static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 434 { 435 struct amd_mp2_dev *privdata; 436 int rc; 437 438 if (dmi_first_match(dmi_nodevs)) 439 return -ENODEV; 440 441 dmi_check_system(dmi_sfh_table); 442 443 privdata = devm_kzalloc(&pdev->dev, sizeof(*privdata), GFP_KERNEL); 444 if (!privdata) 445 return -ENOMEM; 446 447 privdata->pdev = pdev; 448 dev_set_drvdata(&pdev->dev, privdata); 449 rc = pcim_enable_device(pdev); 450 if (rc) 451 return rc; 452 453 rc = pcim_iomap_regions(pdev, BIT(2), DRIVER_NAME); 454 if (rc) 455 return rc; 456 457 privdata->mmio = pcim_iomap_table(pdev)[2]; 458 pci_set_master(pdev); 459 rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 460 if (rc) { 461 dev_err(&pdev->dev, "failed to set DMA mask\n"); 462 return rc; 463 } 464 465 privdata->cl_data = devm_kzalloc(&pdev->dev, sizeof(struct amdtp_cl_data), GFP_KERNEL); 466 if (!privdata->cl_data) 467 return -ENOMEM; 468 469 privdata->sfh1_1_ops = (const struct amd_sfh1_1_ops *)id->driver_data; 470 if (privdata->sfh1_1_ops) { 471 if (boot_cpu_data.x86 >= 0x1A) 472 privdata->rver = 1; 473 474 rc = devm_work_autocancel(&pdev->dev, &privdata->work, sfh1_1_init_work); 475 if (rc) 476 return rc; 477 478 schedule_work(&privdata->work); 479 return 0; 480 } 481 482 mp2_select_ops(privdata); 483 484 rc = amd_sfh_irq_init(privdata); 485 if (rc) { 486 dev_err(&pdev->dev, "amd_sfh_irq_init failed\n"); 487 return rc; 488 } 489 490 rc = devm_work_autocancel(&pdev->dev, &privdata->work, sfh_init_work); 491 if (rc) { 492 amd_sfh_clear_intr(privdata); 493 return rc; 494 } 495 496 schedule_work(&privdata->work); 497 return 0; 498 } 499 500 static void amd_sfh_shutdown(struct pci_dev *pdev) 501 { 502 struct amd_mp2_dev *mp2 = pci_get_drvdata(pdev); 503 504 if (mp2) { 505 flush_work(&mp2->work); 506 if (mp2->init_done) 507 mp2->mp2_ops->stop_all(mp2); 508 } 509 } 510 511 static int __maybe_unused amd_mp2_pci_resume(struct device *dev) 512 { 513 struct amd_mp2_dev *mp2 = dev_get_drvdata(dev); 514 515 flush_work(&mp2->work); 516 if (mp2->init_done) 517 mp2->mp2_ops->resume(mp2); 518 519 return 0; 520 } 521 522 static int __maybe_unused amd_mp2_pci_suspend(struct device *dev) 523 { 524 struct amd_mp2_dev *mp2 = dev_get_drvdata(dev); 525 526 flush_work(&mp2->work); 527 if (mp2->init_done) 528 mp2->mp2_ops->suspend(mp2); 529 530 return 0; 531 } 532 533 static SIMPLE_DEV_PM_OPS(amd_mp2_pm_ops, amd_mp2_pci_suspend, 534 amd_mp2_pci_resume); 535 536 static const struct pci_device_id amd_mp2_pci_tbl[] = { 537 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MP2) }, 538 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MP2_1_1), 539 .driver_data = (kernel_ulong_t)&sfh1_1_ops }, 540 { } 541 }; 542 MODULE_DEVICE_TABLE(pci, amd_mp2_pci_tbl); 543 544 static struct pci_driver amd_mp2_pci_driver = { 545 .name = DRIVER_NAME, 546 .id_table = amd_mp2_pci_tbl, 547 .probe = amd_mp2_pci_probe, 548 .driver.pm = &amd_mp2_pm_ops, 549 .shutdown = amd_sfh_shutdown, 550 .remove = amd_sfh_remove, 551 .dev_groups = amd_sfh_groups, 552 }; 553 module_pci_driver(amd_mp2_pci_driver); 554 555 MODULE_DESCRIPTION(DRIVER_DESC); 556 MODULE_LICENSE("Dual BSD/GPL"); 557 MODULE_AUTHOR("Shyam Sundar S K <Shyam-sundar.S-k@amd.com>"); 558 MODULE_AUTHOR("Sandeep Singh <Sandeep.singh@amd.com>"); 559 MODULE_AUTHOR("Basavaraj Natikar <Basavaraj.Natikar@amd.com>"); 560