1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * AMD MP2 PCIe communication driver 4 * Copyright 2020 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 */ 9 10 #include <linux/bitops.h> 11 #include <linux/delay.h> 12 #include <linux/dma-mapping.h> 13 #include <linux/interrupt.h> 14 #include <linux/io-64-nonatomic-lo-hi.h> 15 #include <linux/module.h> 16 #include <linux/slab.h> 17 18 #include "amd_sfh_pcie.h" 19 20 #define DRIVER_NAME "pcie_mp2_amd" 21 #define DRIVER_DESC "AMD(R) PCIe MP2 Communication Driver" 22 23 #define ACEL_EN BIT(0) 24 #define GYRO_EN BIT(1) 25 #define MAGNO_EN BIT(2) 26 #define ALS_EN BIT(19) 27 28 void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info) 29 { 30 union sfh_cmd_param cmd_param; 31 union sfh_cmd_base cmd_base; 32 33 /* fill up command register */ 34 memset(&cmd_base, 0, sizeof(cmd_base)); 35 cmd_base.s.cmd_id = ENABLE_SENSOR; 36 cmd_base.s.period = info.period; 37 cmd_base.s.sensor_id = info.sensor_idx; 38 39 /* fill up command param register */ 40 memset(&cmd_param, 0, sizeof(cmd_param)); 41 cmd_param.s.buf_layout = 1; 42 cmd_param.s.buf_length = 16; 43 44 writeq(info.phys_address, privdata->mmio + AMD_C2P_MSG2); 45 writel(cmd_param.ul, privdata->mmio + AMD_C2P_MSG1); 46 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); 47 } 48 49 void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx) 50 { 51 union sfh_cmd_base cmd_base; 52 53 /* fill up command register */ 54 memset(&cmd_base, 0, sizeof(cmd_base)); 55 cmd_base.s.cmd_id = DISABLE_SENSOR; 56 cmd_base.s.period = 0; 57 cmd_base.s.sensor_id = sensor_idx; 58 59 writeq(0x0, privdata->mmio + AMD_C2P_MSG2); 60 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); 61 } 62 63 void amd_stop_all_sensors(struct amd_mp2_dev *privdata) 64 { 65 union sfh_cmd_base cmd_base; 66 67 /* fill up command register */ 68 memset(&cmd_base, 0, sizeof(cmd_base)); 69 cmd_base.s.cmd_id = STOP_ALL_SENSORS; 70 cmd_base.s.period = 0; 71 cmd_base.s.sensor_id = 0; 72 73 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); 74 } 75 76 int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id) 77 { 78 int activestatus, num_of_sensors = 0; 79 80 privdata->activecontrolstatus = readl(privdata->mmio + AMD_P2C_MSG3); 81 activestatus = privdata->activecontrolstatus >> 4; 82 if (ACEL_EN & activestatus) 83 sensor_id[num_of_sensors++] = accel_idx; 84 85 if (GYRO_EN & activestatus) 86 sensor_id[num_of_sensors++] = gyro_idx; 87 88 if (MAGNO_EN & activestatus) 89 sensor_id[num_of_sensors++] = mag_idx; 90 91 if (ALS_EN & activestatus) 92 sensor_id[num_of_sensors++] = als_idx; 93 94 return num_of_sensors; 95 } 96 97 static void amd_mp2_pci_remove(void *privdata) 98 { 99 amd_sfh_hid_client_deinit(privdata); 100 amd_stop_all_sensors(privdata); 101 } 102 103 static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 104 { 105 struct amd_mp2_dev *privdata; 106 int rc; 107 108 privdata = devm_kzalloc(&pdev->dev, sizeof(*privdata), GFP_KERNEL); 109 if (!privdata) 110 return -ENOMEM; 111 112 privdata->pdev = pdev; 113 pci_set_drvdata(pdev, privdata); 114 rc = pcim_enable_device(pdev); 115 if (rc) 116 return rc; 117 118 rc = pcim_iomap_regions(pdev, BIT(2), DRIVER_NAME); 119 if (rc) 120 return rc; 121 122 privdata->mmio = pcim_iomap_table(pdev)[2]; 123 pci_set_master(pdev); 124 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); 125 if (rc) { 126 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); 127 return rc; 128 } 129 rc = devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata); 130 if (rc) 131 return rc; 132 133 return amd_sfh_hid_client_init(privdata); 134 } 135 136 static const struct pci_device_id amd_mp2_pci_tbl[] = { 137 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MP2) }, 138 { } 139 }; 140 MODULE_DEVICE_TABLE(pci, amd_mp2_pci_tbl); 141 142 static struct pci_driver amd_mp2_pci_driver = { 143 .name = DRIVER_NAME, 144 .id_table = amd_mp2_pci_tbl, 145 .probe = amd_mp2_pci_probe, 146 }; 147 module_pci_driver(amd_mp2_pci_driver); 148 149 MODULE_DESCRIPTION(DRIVER_DESC); 150 MODULE_LICENSE("Dual BSD/GPL"); 151 MODULE_AUTHOR("Shyam Sundar S K <Shyam-sundar.S-k@amd.com>"); 152 MODULE_AUTHOR("Sandeep Singh <Sandeep.singh@amd.com>"); 153