Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: ccp - Add support for ringing a platform doorbell

Some platforms support using a doorbell to communicate. Export
this feature for other drivers to utilize as well.

Link: https://lore.kernel.org/linux-i2c/20220916131854.687371-3-jsd@semihalf.com/
Suggested-by: Jan Dabros <jsd@semihalf.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Mario Limonciello and committed by
Herbert Xu
d5812571 22351239

+90
+66
drivers/crypto/ccp/platform-access.c
··· 20 20 21 21 #define PSP_CMD_TIMEOUT_US (500 * USEC_PER_MSEC) 22 22 23 + /* Doorbell shouldn't be ringing */ 24 + static int check_doorbell(u32 __iomem *doorbell) 25 + { 26 + u32 tmp; 27 + 28 + return readl_poll_timeout(doorbell, tmp, tmp != 0, 0, PSP_CMD_TIMEOUT_US); 29 + } 30 + 23 31 /* Recovery field should be equal 0 to start sending commands */ 24 32 static int check_recovery(u32 __iomem *cmd) 25 33 { ··· 140 132 } 141 133 EXPORT_SYMBOL_GPL(psp_send_platform_access_msg); 142 134 135 + int psp_ring_platform_doorbell(int msg) 136 + { 137 + struct psp_device *psp = psp_get_master_device(); 138 + struct psp_platform_access_device *pa_dev; 139 + u32 __iomem *button, *cmd; 140 + int ret, val; 141 + 142 + if (!psp || !psp->platform_access_data) 143 + return -ENODEV; 144 + 145 + pa_dev = psp->platform_access_data; 146 + button = psp->io_regs + pa_dev->vdata->doorbell_button_reg; 147 + cmd = psp->io_regs + pa_dev->vdata->doorbell_cmd_reg; 148 + 149 + mutex_lock(&pa_dev->doorbell_mutex); 150 + 151 + if (check_doorbell(button)) { 152 + dev_dbg(psp->dev, "doorbell is not ready\n"); 153 + ret = -EBUSY; 154 + goto unlock; 155 + } 156 + 157 + if (check_recovery(cmd)) { 158 + dev_dbg(psp->dev, "doorbell command in recovery\n"); 159 + ret = -EBUSY; 160 + goto unlock; 161 + } 162 + 163 + if (wait_cmd(cmd)) { 164 + dev_dbg(psp->dev, "doorbell command not done processing\n"); 165 + ret = -EBUSY; 166 + goto unlock; 167 + } 168 + 169 + iowrite32(FIELD_PREP(PSP_DRBL_MSG, msg), cmd); 170 + iowrite32(PSP_DRBL_RING, button); 171 + 172 + if (wait_cmd(cmd)) { 173 + ret = -ETIMEDOUT; 174 + goto unlock; 175 + } 176 + 177 + val = FIELD_GET(PSP_CMDRESP_STS, ioread32(cmd)); 178 + if (val) { 179 + ret = -EIO; 180 + goto unlock; 181 + } 182 + 183 + ret = 0; 184 + unlock: 185 + mutex_unlock(&pa_dev->doorbell_mutex); 186 + 187 + return ret; 188 + } 189 + EXPORT_SYMBOL_GPL(psp_ring_platform_doorbell); 190 + 143 191 void platform_access_dev_destroy(struct psp_device *psp) 144 192 { 145 193 struct psp_platform_access_device *pa_dev = psp->platform_access_data; ··· 204 140 return; 205 141 206 142 mutex_destroy(&pa_dev->mailbox_mutex); 143 + mutex_destroy(&pa_dev->doorbell_mutex); 207 144 psp->platform_access_data = NULL; 208 145 } 209 146 ··· 224 159 pa_dev->vdata = (struct platform_access_vdata *)psp->vdata->platform_access; 225 160 226 161 mutex_init(&pa_dev->mailbox_mutex); 162 + mutex_init(&pa_dev->doorbell_mutex); 227 163 228 164 dev_dbg(dev, "platform access enabled\n"); 229 165
+1
drivers/crypto/ccp/platform-access.h
··· 24 24 struct platform_access_vdata *vdata; 25 25 26 26 struct mutex mailbox_mutex; 27 + struct mutex doorbell_mutex; 27 28 28 29 void *platform_access_data; 29 30 };
+3
drivers/crypto/ccp/sp-dev.h
··· 57 57 const unsigned int cmdresp_reg; 58 58 const unsigned int cmdbuff_addr_lo_reg; 59 59 const unsigned int cmdbuff_addr_hi_reg; 60 + const unsigned int doorbell_button_reg; 61 + const unsigned int doorbell_cmd_reg; 62 + 60 63 }; 61 64 62 65 struct psp_vdata {
+2
drivers/crypto/ccp/sp-pci.c
··· 365 365 .cmdresp_reg = 0x10570, /* C2PMSG_28 */ 366 366 .cmdbuff_addr_lo_reg = 0x10574, /* C2PMSG_29 */ 367 367 .cmdbuff_addr_hi_reg = 0x10578, /* C2PMSG_30 */ 368 + .doorbell_button_reg = 0x10a24, /* C2PMSG_73 */ 369 + .doorbell_cmd_reg = 0x10a40, /* C2PMSG_80 */ 368 370 }; 369 371 370 372 static const struct psp_vdata pspv1 = {
+15
include/linux/psp-platform-access.h
··· 35 35 int psp_send_platform_access_msg(enum psp_platform_access_msg, struct psp_request *req); 36 36 37 37 /** 38 + * psp_ring_platform_doorbell() - Ring platform doorbell 39 + * 40 + * This function is intended to be used by drivers outside of ccp to ring the 41 + * platform doorbell with a message. 42 + * 43 + * Returns: 44 + * 0: success 45 + * -%EBUSY: mailbox in recovery or in use 46 + * -%ENODEV: driver not bound with PSP device 47 + * -%ETIMEDOUT: request timed out 48 + * -%EIO: unknown error (see kernel log) 49 + */ 50 + int psp_ring_platform_doorbell(int msg); 51 + 52 + /** 38 53 * psp_check_platform_access_status() - Checks whether platform features is ready 39 54 * 40 55 * This function is intended to be used by drivers outside of ccp to determine
+3
include/linux/psp.h
··· 23 23 #define PSP_CMDRESP_RECOVERY BIT(30) 24 24 #define PSP_CMDRESP_RESP BIT(31) 25 25 26 + #define PSP_DRBL_MSG PSP_CMDRESP_CMD 27 + #define PSP_DRBL_RING BIT(0) 28 + 26 29 #endif /* __PSP_H */