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