1f40008a4SJulius Werner /* 2f40008a4SJulius Werner * Copyright (c) 2020, Google LLC. All rights reserved. 3f40008a4SJulius Werner * 4f40008a4SJulius Werner * SPDX-License-Identifier: BSD-3-Clause 5f40008a4SJulius Werner */ 6f40008a4SJulius Werner 7f40008a4SJulius Werner #include <common/debug.h> 8f40008a4SJulius Werner #include <drivers/delay_timer.h> 9f40008a4SJulius Werner #include <lib/mmio.h> 10f40008a4SJulius Werner 11f40008a4SJulius Werner #include <spmi_arb.h> 12f40008a4SJulius Werner 13*9694c210SJulius Werner #define REG_APID_MAP(apid) (0x0C440900U + 4U * i) 14f40008a4SJulius Werner #define NUM_APID 0x80 15f40008a4SJulius Werner 16*9694c210SJulius Werner #define PPID_MASK (0xfffU << 8) 17f40008a4SJulius Werner 18*9694c210SJulius Werner #define REG_ARB_CMD(apid) (0x0C600000U + 0x10000U * apid) 19f40008a4SJulius Werner /* These are opcodes specific to this SPMI arbitrator, *not* SPMI commands. */ 20f40008a4SJulius Werner #define OPC_EXT_WRITEL 0 21f40008a4SJulius Werner #define OPC_EXT_READL 1 22f40008a4SJulius Werner 23*9694c210SJulius Werner #define REG_ARB_STATUS(apid) (0x0C600008U + 0x10000U * apid) 24f40008a4SJulius Werner #define ARB_STATUS_DONE BIT(0) 25f40008a4SJulius Werner #define ARB_STATUS_FAILURE BIT(1) 26f40008a4SJulius Werner #define ARB_STATUS_DENIED BIT(2) 27f40008a4SJulius Werner #define ARB_STATUS_DROPPED BIT(3) 28f40008a4SJulius Werner 29f40008a4SJulius Werner /* Fake status to report driver errors. */ 30f40008a4SJulius Werner #define ARB_FAKE_STATUS_TIMEOUT BIT(8) 31f40008a4SJulius Werner 32*9694c210SJulius Werner #define REG_ARB_RDATA0(apid) (0x0C600018U + 0x10000U * apid) 33*9694c210SJulius Werner #define REG_ARB_WDATA0(apid) (0x0C600010U + 0x10000U * apid) 34f40008a4SJulius Werner 35f40008a4SJulius Werner static int addr_to_apid(uint32_t addr) 36f40008a4SJulius Werner { 37f40008a4SJulius Werner unsigned int i; 38f40008a4SJulius Werner 39f40008a4SJulius Werner for (i = 0U; i < NUM_APID; i++) { 40f40008a4SJulius Werner uint32_t reg = mmio_read_32(REG_APID_MAP(i)); 41f40008a4SJulius Werner if ((reg != 0U) && ((addr & PPID_MASK) == (reg & PPID_MASK))) { 42f40008a4SJulius Werner return i; 43f40008a4SJulius Werner } 44f40008a4SJulius Werner } 45f40008a4SJulius Werner 46f40008a4SJulius Werner return -1; 47f40008a4SJulius Werner } 48f40008a4SJulius Werner 49f40008a4SJulius Werner static int wait_for_done(uint16_t apid) 50f40008a4SJulius Werner { 51f40008a4SJulius Werner unsigned int timeout = 100; 52f40008a4SJulius Werner 53f40008a4SJulius Werner while (timeout-- != 0U) { 54f40008a4SJulius Werner uint32_t status = mmio_read_32(REG_ARB_STATUS(apid)); 55f40008a4SJulius Werner if ((status & ARB_STATUS_DONE) != 0U) { 56f40008a4SJulius Werner if ((status & ARB_STATUS_FAILURE) != 0U || 57f40008a4SJulius Werner (status & ARB_STATUS_DENIED) != 0U || 58f40008a4SJulius Werner (status & ARB_STATUS_DROPPED) != 0U) { 59f40008a4SJulius Werner return status & 0xff; 60f40008a4SJulius Werner } 61f40008a4SJulius Werner return 0; 62f40008a4SJulius Werner } 63f40008a4SJulius Werner mdelay(1); 64f40008a4SJulius Werner } 65f40008a4SJulius Werner ERROR("SPMI_ARB timeout!\n"); 66f40008a4SJulius Werner return ARB_FAKE_STATUS_TIMEOUT; 67f40008a4SJulius Werner } 68f40008a4SJulius Werner 69f40008a4SJulius Werner static void arb_command(uint16_t apid, uint8_t opcode, uint32_t addr, 70f40008a4SJulius Werner uint8_t bytes) 71f40008a4SJulius Werner { 72f40008a4SJulius Werner mmio_write_32(REG_ARB_CMD(apid), (uint32_t)opcode << 27 | 73f40008a4SJulius Werner (addr & 0xff) << 4 | (bytes - 1)); 74f40008a4SJulius Werner } 75f40008a4SJulius Werner 76f40008a4SJulius Werner int spmi_arb_read8(uint32_t addr) 77f40008a4SJulius Werner { 78f40008a4SJulius Werner int apid = addr_to_apid(addr); 79f40008a4SJulius Werner 80f40008a4SJulius Werner if (apid < 0) { 81f40008a4SJulius Werner return apid; 82f40008a4SJulius Werner } 83f40008a4SJulius Werner 84f40008a4SJulius Werner arb_command(apid, OPC_EXT_READL, addr, 1); 85f40008a4SJulius Werner 86f40008a4SJulius Werner int ret = wait_for_done(apid); 87f40008a4SJulius Werner if (ret != 0) { 88f40008a4SJulius Werner ERROR("SPMI_ARB read error [0x%x]: 0x%x\n", addr, ret); 89f40008a4SJulius Werner return ret; 90f40008a4SJulius Werner } 91f40008a4SJulius Werner 92f40008a4SJulius Werner return mmio_read_32(REG_ARB_RDATA0(apid)) & 0xff; 93f40008a4SJulius Werner } 94f40008a4SJulius Werner 95f40008a4SJulius Werner int spmi_arb_write8(uint32_t addr, uint8_t data) 96f40008a4SJulius Werner { 97f40008a4SJulius Werner int apid = addr_to_apid(addr); 98f40008a4SJulius Werner 99f40008a4SJulius Werner if (apid < 0) { 100f40008a4SJulius Werner return apid; 101f40008a4SJulius Werner } 102f40008a4SJulius Werner 103f40008a4SJulius Werner mmio_write_32(REG_ARB_WDATA0(apid), data); 104f40008a4SJulius Werner arb_command(apid, OPC_EXT_WRITEL, addr, 1); 105f40008a4SJulius Werner 106f40008a4SJulius Werner int ret = wait_for_done(apid); 107f40008a4SJulius Werner if (ret != 0) { 108f40008a4SJulius Werner ERROR("SPMI_ARB write error [0x%x] = 0x%x: 0x%x\n", 109f40008a4SJulius Werner addr, data, ret); 110f40008a4SJulius Werner } 111f40008a4SJulius Werner 112f40008a4SJulius Werner return ret; 113f40008a4SJulius Werner } 114