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/dma-mapping.h> 14 #include <linux/dmi.h> 15 #include <linux/interrupt.h> 16 #include <linux/io-64-nonatomic-lo-hi.h> 17 #include <linux/iopoll.h> 18 #include <linux/module.h> 19 #include <linux/slab.h> 20 21 #include "amd_sfh_pcie.h" 22 23 #define DRIVER_NAME "pcie_mp2_amd" 24 #define DRIVER_DESC "AMD(R) PCIe MP2 Communication Driver" 25 26 #define ACEL_EN BIT(0) 27 #define GYRO_EN BIT(1) 28 #define MAGNO_EN BIT(2) 29 #define HPD_EN BIT(16) 30 #define ALS_EN BIT(19) 31 32 static int sensor_mask_override = -1; 33 module_param_named(sensor_mask, sensor_mask_override, int, 0444); 34 MODULE_PARM_DESC(sensor_mask, "override the detected sensors mask"); 35 36 static int amd_sfh_wait_response_v2(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts) 37 { 38 union cmd_response cmd_resp; 39 40 /* Get response with status within a max of 1600 ms timeout */ 41 if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG(0), cmd_resp.resp, 42 (cmd_resp.response_v2.response == sensor_sts && 43 cmd_resp.response_v2.status == 0 && (sid == 0xff || 44 cmd_resp.response_v2.sensor_id == sid)), 500, 1600000)) 45 return cmd_resp.response_v2.response; 46 47 return SENSOR_DISABLED; 48 } 49 50 static void amd_start_sensor_v2(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info) 51 { 52 union sfh_cmd_base cmd_base; 53 54 cmd_base.ul = 0; 55 cmd_base.cmd_v2.cmd_id = ENABLE_SENSOR; 56 cmd_base.cmd_v2.intr_disable = 1; 57 cmd_base.cmd_v2.period = info.period; 58 cmd_base.cmd_v2.sensor_id = info.sensor_idx; 59 cmd_base.cmd_v2.length = 16; 60 61 if (info.sensor_idx == als_idx) 62 cmd_base.cmd_v2.mem_type = USE_C2P_REG; 63 64 writeq(info.dma_address, privdata->mmio + AMD_C2P_MSG1); 65 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); 66 } 67 68 static void amd_stop_sensor_v2(struct amd_mp2_dev *privdata, u16 sensor_idx) 69 { 70 union sfh_cmd_base cmd_base; 71 72 cmd_base.ul = 0; 73 cmd_base.cmd_v2.cmd_id = DISABLE_SENSOR; 74 cmd_base.cmd_v2.intr_disable = 1; 75 cmd_base.cmd_v2.period = 0; 76 cmd_base.cmd_v2.sensor_id = sensor_idx; 77 cmd_base.cmd_v2.length = 16; 78 79 writeq(0x0, privdata->mmio + AMD_C2P_MSG1); 80 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); 81 } 82 83 static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata) 84 { 85 union sfh_cmd_base cmd_base; 86 87 cmd_base.cmd_v2.cmd_id = STOP_ALL_SENSORS; 88 cmd_base.cmd_v2.intr_disable = 1; 89 cmd_base.cmd_v2.period = 0; 90 cmd_base.cmd_v2.sensor_id = 0; 91 92 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); 93 } 94 95 static void amd_sfh_clear_intr_v2(struct amd_mp2_dev *privdata) 96 { 97 if (readl(privdata->mmio + AMD_P2C_MSG(4))) { 98 writel(0, privdata->mmio + AMD_P2C_MSG(4)); 99 writel(0xf, privdata->mmio + AMD_P2C_MSG(5)); 100 } 101 } 102 103 static void amd_sfh_clear_intr(struct amd_mp2_dev *privdata) 104 { 105 if (privdata->mp2_ops->clear_intr) 106 privdata->mp2_ops->clear_intr(privdata); 107 } 108 109 static irqreturn_t amd_sfh_irq_handler(int irq, void *data) 110 { 111 amd_sfh_clear_intr(data); 112 113 return IRQ_HANDLED; 114 } 115 116 static int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata) 117 { 118 int rc; 119 120 pci_intx(privdata->pdev, true); 121 122 rc = devm_request_irq(&privdata->pdev->dev, privdata->pdev->irq, 123 amd_sfh_irq_handler, 0, DRIVER_NAME, privdata); 124 if (rc) { 125 dev_err(&privdata->pdev->dev, "failed to request irq %d err=%d\n", 126 privdata->pdev->irq, rc); 127 return rc; 128 } 129 130 return 0; 131 } 132 133 void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info) 134 { 135 union sfh_cmd_param cmd_param; 136 union sfh_cmd_base cmd_base; 137 138 /* fill up command register */ 139 memset(&cmd_base, 0, sizeof(cmd_base)); 140 cmd_base.s.cmd_id = ENABLE_SENSOR; 141 cmd_base.s.period = info.period; 142 cmd_base.s.sensor_id = info.sensor_idx; 143 144 /* fill up command param register */ 145 memset(&cmd_param, 0, sizeof(cmd_param)); 146 cmd_param.s.buf_layout = 1; 147 cmd_param.s.buf_length = 16; 148 149 writeq(info.dma_address, privdata->mmio + AMD_C2P_MSG2); 150 writel(cmd_param.ul, privdata->mmio + AMD_C2P_MSG1); 151 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); 152 } 153 154 void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx) 155 { 156 union sfh_cmd_base cmd_base; 157 158 /* fill up command register */ 159 memset(&cmd_base, 0, sizeof(cmd_base)); 160 cmd_base.s.cmd_id = DISABLE_SENSOR; 161 cmd_base.s.period = 0; 162 cmd_base.s.sensor_id = sensor_idx; 163 164 writeq(0x0, privdata->mmio + AMD_C2P_MSG2); 165 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); 166 } 167 168 void amd_stop_all_sensors(struct amd_mp2_dev *privdata) 169 { 170 union sfh_cmd_base cmd_base; 171 172 /* fill up command register */ 173 memset(&cmd_base, 0, sizeof(cmd_base)); 174 cmd_base.s.cmd_id = STOP_ALL_SENSORS; 175 cmd_base.s.period = 0; 176 cmd_base.s.sensor_id = 0; 177 178 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); 179 } 180 181 static const struct dmi_system_id dmi_sensor_mask_overrides[] = { 182 { 183 .matches = { 184 DMI_MATCH(DMI_PRODUCT_NAME, "HP ENVY x360 Convertible 13-ag0xxx"), 185 }, 186 .driver_data = (void *)(ACEL_EN | MAGNO_EN), 187 }, 188 { 189 .matches = { 190 DMI_MATCH(DMI_PRODUCT_NAME, "HP ENVY x360 Convertible 15-cp0xxx"), 191 }, 192 .driver_data = (void *)(ACEL_EN | MAGNO_EN), 193 }, 194 { } 195 }; 196 197 int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id) 198 { 199 int activestatus, num_of_sensors = 0; 200 const struct dmi_system_id *dmi_id; 201 202 if (sensor_mask_override == -1) { 203 dmi_id = dmi_first_match(dmi_sensor_mask_overrides); 204 if (dmi_id) 205 sensor_mask_override = (long)dmi_id->driver_data; 206 } 207 208 if (sensor_mask_override >= 0) { 209 activestatus = sensor_mask_override; 210 } else { 211 activestatus = privdata->mp2_acs >> 4; 212 } 213 214 if (ACEL_EN & activestatus) 215 sensor_id[num_of_sensors++] = accel_idx; 216 217 if (GYRO_EN & activestatus) 218 sensor_id[num_of_sensors++] = gyro_idx; 219 220 if (MAGNO_EN & activestatus) 221 sensor_id[num_of_sensors++] = mag_idx; 222 223 if (ALS_EN & activestatus) 224 sensor_id[num_of_sensors++] = als_idx; 225 226 if (HPD_EN & activestatus) 227 sensor_id[num_of_sensors++] = HPD_IDX; 228 229 return num_of_sensors; 230 } 231 232 static void amd_mp2_pci_remove(void *privdata) 233 { 234 struct amd_mp2_dev *mp2 = privdata; 235 amd_sfh_hid_client_deinit(privdata); 236 mp2->mp2_ops->stop_all(mp2); 237 pci_intx(mp2->pdev, false); 238 amd_sfh_clear_intr(mp2); 239 } 240 241 static const struct amd_mp2_ops amd_sfh_ops_v2 = { 242 .start = amd_start_sensor_v2, 243 .stop = amd_stop_sensor_v2, 244 .stop_all = amd_stop_all_sensor_v2, 245 .response = amd_sfh_wait_response_v2, 246 .clear_intr = amd_sfh_clear_intr_v2, 247 .init_intr = amd_sfh_irq_init_v2, 248 }; 249 250 static const struct amd_mp2_ops amd_sfh_ops = { 251 .start = amd_start_sensor, 252 .stop = amd_stop_sensor, 253 .stop_all = amd_stop_all_sensors, 254 }; 255 256 static void mp2_select_ops(struct amd_mp2_dev *privdata) 257 { 258 u8 acs; 259 260 privdata->mp2_acs = readl(privdata->mmio + AMD_P2C_MSG3); 261 acs = privdata->mp2_acs & GENMASK(3, 0); 262 263 switch (acs) { 264 case V2_STATUS: 265 privdata->mp2_ops = &amd_sfh_ops_v2; 266 break; 267 default: 268 privdata->mp2_ops = &amd_sfh_ops; 269 break; 270 } 271 } 272 273 static int amd_sfh_irq_init(struct amd_mp2_dev *privdata) 274 { 275 if (privdata->mp2_ops->init_intr) 276 return privdata->mp2_ops->init_intr(privdata); 277 278 return 0; 279 } 280 281 static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 282 { 283 struct amd_mp2_dev *privdata; 284 int rc; 285 286 privdata = devm_kzalloc(&pdev->dev, sizeof(*privdata), GFP_KERNEL); 287 if (!privdata) 288 return -ENOMEM; 289 290 privdata->pdev = pdev; 291 dev_set_drvdata(&pdev->dev, privdata); 292 rc = pcim_enable_device(pdev); 293 if (rc) 294 return rc; 295 296 rc = pcim_iomap_regions(pdev, BIT(2), DRIVER_NAME); 297 if (rc) 298 return rc; 299 300 privdata->mmio = pcim_iomap_table(pdev)[2]; 301 pci_set_master(pdev); 302 rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 303 if (rc) { 304 dev_err(&pdev->dev, "failed to set DMA mask\n"); 305 return rc; 306 } 307 308 privdata->cl_data = devm_kzalloc(&pdev->dev, sizeof(struct amdtp_cl_data), GFP_KERNEL); 309 if (!privdata->cl_data) 310 return -ENOMEM; 311 312 mp2_select_ops(privdata); 313 314 rc = amd_sfh_irq_init(privdata); 315 if (rc) { 316 dev_err(&pdev->dev, "amd_sfh_irq_init failed\n"); 317 return rc; 318 } 319 320 rc = amd_sfh_hid_client_init(privdata); 321 if (rc) { 322 amd_sfh_clear_intr(privdata); 323 dev_err(&pdev->dev, "amd_sfh_hid_client_init failed\n"); 324 return rc; 325 } 326 327 amd_sfh_clear_intr(privdata); 328 329 return devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata); 330 } 331 332 static int __maybe_unused amd_mp2_pci_resume(struct device *dev) 333 { 334 struct amd_mp2_dev *mp2 = dev_get_drvdata(dev); 335 struct amdtp_cl_data *cl_data = mp2->cl_data; 336 struct amd_mp2_sensor_info info; 337 int i, status; 338 339 for (i = 0; i < cl_data->num_hid_devices; i++) { 340 if (cl_data->sensor_sts[i] == SENSOR_DISABLED) { 341 info.period = AMD_SFH_IDLE_LOOP; 342 info.sensor_idx = cl_data->sensor_idx[i]; 343 info.dma_address = cl_data->sensor_dma_addr[i]; 344 mp2->mp2_ops->start(mp2, info); 345 status = amd_sfh_wait_for_response 346 (mp2, cl_data->sensor_idx[i], SENSOR_ENABLED); 347 if (status == SENSOR_ENABLED) 348 cl_data->sensor_sts[i] = SENSOR_ENABLED; 349 dev_dbg(dev, "resume sid 0x%x status 0x%x\n", 350 cl_data->sensor_idx[i], cl_data->sensor_sts[i]); 351 } 352 } 353 354 schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP)); 355 amd_sfh_clear_intr(mp2); 356 357 return 0; 358 } 359 360 static int __maybe_unused amd_mp2_pci_suspend(struct device *dev) 361 { 362 struct amd_mp2_dev *mp2 = dev_get_drvdata(dev); 363 struct amdtp_cl_data *cl_data = mp2->cl_data; 364 int i, status; 365 366 for (i = 0; i < cl_data->num_hid_devices; i++) { 367 if (cl_data->sensor_idx[i] != HPD_IDX && 368 cl_data->sensor_sts[i] == SENSOR_ENABLED) { 369 mp2->mp2_ops->stop(mp2, cl_data->sensor_idx[i]); 370 status = amd_sfh_wait_for_response 371 (mp2, cl_data->sensor_idx[i], SENSOR_DISABLED); 372 if (status != SENSOR_ENABLED) 373 cl_data->sensor_sts[i] = SENSOR_DISABLED; 374 dev_dbg(dev, "suspend sid 0x%x status 0x%x\n", 375 cl_data->sensor_idx[i], cl_data->sensor_sts[i]); 376 } 377 } 378 379 cancel_delayed_work_sync(&cl_data->work_buffer); 380 amd_sfh_clear_intr(mp2); 381 382 return 0; 383 } 384 385 static SIMPLE_DEV_PM_OPS(amd_mp2_pm_ops, amd_mp2_pci_suspend, 386 amd_mp2_pci_resume); 387 388 static const struct pci_device_id amd_mp2_pci_tbl[] = { 389 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MP2) }, 390 { } 391 }; 392 MODULE_DEVICE_TABLE(pci, amd_mp2_pci_tbl); 393 394 static struct pci_driver amd_mp2_pci_driver = { 395 .name = DRIVER_NAME, 396 .id_table = amd_mp2_pci_tbl, 397 .probe = amd_mp2_pci_probe, 398 .driver.pm = &amd_mp2_pm_ops, 399 }; 400 module_pci_driver(amd_mp2_pci_driver); 401 402 MODULE_DESCRIPTION(DRIVER_DESC); 403 MODULE_LICENSE("Dual BSD/GPL"); 404 MODULE_AUTHOR("Shyam Sundar S K <Shyam-sundar.S-k@amd.com>"); 405 MODULE_AUTHOR("Sandeep Singh <Sandeep.singh@amd.com>"); 406 MODULE_AUTHOR("Basavaraj Natikar <Basavaraj.Natikar@amd.com>"); 407