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