1*9fc34bbdSkenny liang /* 2*9fc34bbdSkenny liang * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. 3*9fc34bbdSkenny liang * 4*9fc34bbdSkenny liang * SPDX-License-Identifier: BSD-3-Clause 5*9fc34bbdSkenny liang */ 6*9fc34bbdSkenny liang #include <arch_helpers.h> 7*9fc34bbdSkenny liang #include <common/debug.h> 8*9fc34bbdSkenny liang #include <drivers/delay_timer.h> 9*9fc34bbdSkenny liang #include <errno.h> 10*9fc34bbdSkenny liang #include <lib/mmio.h> 11*9fc34bbdSkenny liang #include <sspm.h> 12*9fc34bbdSkenny liang 13*9fc34bbdSkenny liang static void memcpy_to_sspm(uint32_t dst, uint32_t *src, uint32_t len) 14*9fc34bbdSkenny liang { 15*9fc34bbdSkenny liang while (len--) { 16*9fc34bbdSkenny liang mmio_write_32(dst, *src); 17*9fc34bbdSkenny liang dst += sizeof(uint32_t); 18*9fc34bbdSkenny liang src++; 19*9fc34bbdSkenny liang } 20*9fc34bbdSkenny liang } 21*9fc34bbdSkenny liang 22*9fc34bbdSkenny liang static void memcpy_from_sspm(uint32_t *dst, uint32_t src, uint32_t len) 23*9fc34bbdSkenny liang { 24*9fc34bbdSkenny liang while (len--) { 25*9fc34bbdSkenny liang *dst = mmio_read_32(src); 26*9fc34bbdSkenny liang dst++; 27*9fc34bbdSkenny liang src += sizeof(uint32_t); 28*9fc34bbdSkenny liang } 29*9fc34bbdSkenny liang } 30*9fc34bbdSkenny liang 31*9fc34bbdSkenny liang int sspm_mbox_read(uint32_t slot, uint32_t *data, uint32_t len) 32*9fc34bbdSkenny liang { 33*9fc34bbdSkenny liang if (slot >= 32) { 34*9fc34bbdSkenny liang ERROR("%s:slot = %d\n", __func__, slot); 35*9fc34bbdSkenny liang return -EINVAL; 36*9fc34bbdSkenny liang } 37*9fc34bbdSkenny liang 38*9fc34bbdSkenny liang if (data) 39*9fc34bbdSkenny liang memcpy_from_sspm(data, 40*9fc34bbdSkenny liang MBOX3_BASE + slot * 4, 41*9fc34bbdSkenny liang len); 42*9fc34bbdSkenny liang 43*9fc34bbdSkenny liang return 0; 44*9fc34bbdSkenny liang } 45*9fc34bbdSkenny liang 46*9fc34bbdSkenny liang int sspm_mbox_write(uint32_t slot, uint32_t *data, uint32_t len) 47*9fc34bbdSkenny liang { 48*9fc34bbdSkenny liang if (slot >= 32) { 49*9fc34bbdSkenny liang ERROR("%s:slot = %d\n", __func__, slot); 50*9fc34bbdSkenny liang return -EINVAL; 51*9fc34bbdSkenny liang } 52*9fc34bbdSkenny liang 53*9fc34bbdSkenny liang if (data) 54*9fc34bbdSkenny liang memcpy_to_sspm(MBOX3_BASE + slot * 4, 55*9fc34bbdSkenny liang data, 56*9fc34bbdSkenny liang len); 57*9fc34bbdSkenny liang 58*9fc34bbdSkenny liang return 0; 59*9fc34bbdSkenny liang } 60*9fc34bbdSkenny liang 61*9fc34bbdSkenny liang static int sspm_ipi_check_ack(uint32_t id) 62*9fc34bbdSkenny liang { 63*9fc34bbdSkenny liang int ret = 0; 64*9fc34bbdSkenny liang 65*9fc34bbdSkenny liang if (id == IPI_ID_PLATFORM) { 66*9fc34bbdSkenny liang if ((mmio_read_32(MBOX0_BASE + MBOX_IN_IRQ_OFS) & 0x1) == 0x1) 67*9fc34bbdSkenny liang ret = -EINPROGRESS; 68*9fc34bbdSkenny liang } else if (id == IPI_ID_SUSPEND) { 69*9fc34bbdSkenny liang if ((mmio_read_32(MBOX1_BASE + MBOX_IN_IRQ_OFS) & 0x2) == 0x2) 70*9fc34bbdSkenny liang ret = -EINPROGRESS; 71*9fc34bbdSkenny liang } else { 72*9fc34bbdSkenny liang ERROR("%s: id = %d\n", __func__, id); 73*9fc34bbdSkenny liang ret = -EINVAL; 74*9fc34bbdSkenny liang } 75*9fc34bbdSkenny liang 76*9fc34bbdSkenny liang return ret; 77*9fc34bbdSkenny liang } 78*9fc34bbdSkenny liang 79*9fc34bbdSkenny liang int sspm_ipi_send_non_blocking(uint32_t id, uint32_t *data) 80*9fc34bbdSkenny liang { 81*9fc34bbdSkenny liang int ret = 0; 82*9fc34bbdSkenny liang 83*9fc34bbdSkenny liang ret = sspm_ipi_check_ack(id); 84*9fc34bbdSkenny liang if (ret) 85*9fc34bbdSkenny liang return ret; 86*9fc34bbdSkenny liang 87*9fc34bbdSkenny liang if (id == IPI_ID_PLATFORM) { 88*9fc34bbdSkenny liang memcpy_to_sspm(MBOX0_BASE + PINR_OFFSET_PLATFORM * 4, 89*9fc34bbdSkenny liang data, 90*9fc34bbdSkenny liang PINR_SIZE_PLATFORM); 91*9fc34bbdSkenny liang dsb(); 92*9fc34bbdSkenny liang mmio_write_32(MBOX0_BASE + MBOX_OUT_IRQ_OFS, 0x1); 93*9fc34bbdSkenny liang } else if (id == IPI_ID_SUSPEND) { 94*9fc34bbdSkenny liang memcpy_to_sspm(MBOX1_BASE + PINR_OFFSET_SUSPEND * 4, 95*9fc34bbdSkenny liang data, 96*9fc34bbdSkenny liang PINR_SIZE_SUSPEND); 97*9fc34bbdSkenny liang dsb(); 98*9fc34bbdSkenny liang mmio_write_32(MBOX1_BASE + MBOX_OUT_IRQ_OFS, 99*9fc34bbdSkenny liang 0x2); 100*9fc34bbdSkenny liang } 101*9fc34bbdSkenny liang 102*9fc34bbdSkenny liang return 0; 103*9fc34bbdSkenny liang } 104*9fc34bbdSkenny liang 105*9fc34bbdSkenny liang int sspm_ipi_recv_non_blocking(uint32_t id, uint32_t *data, uint32_t len) 106*9fc34bbdSkenny liang { 107*9fc34bbdSkenny liang int ret = 0; 108*9fc34bbdSkenny liang 109*9fc34bbdSkenny liang ret = sspm_ipi_check_ack(id); 110*9fc34bbdSkenny liang if (ret == -EINPROGRESS) { 111*9fc34bbdSkenny liang if (id == IPI_ID_PLATFORM) { 112*9fc34bbdSkenny liang memcpy_from_sspm(data, 113*9fc34bbdSkenny liang MBOX0_BASE + PINR_OFFSET_PLATFORM * 4, 114*9fc34bbdSkenny liang len); 115*9fc34bbdSkenny liang dsb(); 116*9fc34bbdSkenny liang /* clear interrupt bit*/ 117*9fc34bbdSkenny liang mmio_write_32(MBOX0_BASE + MBOX_IN_IRQ_OFS, 118*9fc34bbdSkenny liang 0x1); 119*9fc34bbdSkenny liang ret = 0; 120*9fc34bbdSkenny liang } else if (id == IPI_ID_SUSPEND) { 121*9fc34bbdSkenny liang memcpy_from_sspm(data, 122*9fc34bbdSkenny liang MBOX1_BASE + PINR_OFFSET_SUSPEND * 4, 123*9fc34bbdSkenny liang len); 124*9fc34bbdSkenny liang dsb(); 125*9fc34bbdSkenny liang /* clear interrupt bit*/ 126*9fc34bbdSkenny liang mmio_write_32(MBOX1_BASE + MBOX_IN_IRQ_OFS, 127*9fc34bbdSkenny liang 0x2); 128*9fc34bbdSkenny liang ret = 0; 129*9fc34bbdSkenny liang } 130*9fc34bbdSkenny liang } else if (ret == 0) { 131*9fc34bbdSkenny liang ret = -EBUSY; 132*9fc34bbdSkenny liang } 133*9fc34bbdSkenny liang 134*9fc34bbdSkenny liang return ret; 135*9fc34bbdSkenny liang } 136*9fc34bbdSkenny liang 137*9fc34bbdSkenny liang int sspm_alive_show(void) 138*9fc34bbdSkenny liang { 139*9fc34bbdSkenny liang uint32_t ipi_data, count; 140*9fc34bbdSkenny liang int ret = 0; 141*9fc34bbdSkenny liang 142*9fc34bbdSkenny liang count = 5; 143*9fc34bbdSkenny liang ipi_data = 0xdead; 144*9fc34bbdSkenny liang 145*9fc34bbdSkenny liang if (sspm_ipi_send_non_blocking(IPI_ID_PLATFORM, &ipi_data) != 0) { 146*9fc34bbdSkenny liang ERROR("sspm init send fail! ret=%d\n", ret); 147*9fc34bbdSkenny liang return -1; 148*9fc34bbdSkenny liang } 149*9fc34bbdSkenny liang 150*9fc34bbdSkenny liang while (sspm_ipi_recv_non_blocking(IPI_ID_PLATFORM, 151*9fc34bbdSkenny liang &ipi_data, 152*9fc34bbdSkenny liang sizeof(ipi_data)) 153*9fc34bbdSkenny liang && count) { 154*9fc34bbdSkenny liang mdelay(100); 155*9fc34bbdSkenny liang count--; 156*9fc34bbdSkenny liang } 157*9fc34bbdSkenny liang 158*9fc34bbdSkenny liang return (ipi_data == 1) ? 0 : -1; 159*9fc34bbdSkenny liang } 160