| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- /* Copyright Statement:
- *
- * This software/firmware and related documentation ("MediaTek Software") are
- * protected under relevant copyright laws. The information contained herein is
- * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
- * the prior written permission of MediaTek inc. and/or its licensors, any
- * reproduction, modification, use or disclosure of MediaTek Software, and
- * information contained herein, in whole or in part, shall be strictly
- * prohibited.
- *
- * MediaTek Inc. (C) 2019. All rights reserved.
- *
- * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
- * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
- * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
- * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
- * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
- * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
- * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
- * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
- * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
- * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
- * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
- * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
- * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
- * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
- * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
- * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
- * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
- * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
- *
- * The following software/firmware and/or related documentation ("MediaTek
- * Software") have been modified by MediaTek Inc. All revisions are subject to
- * any receiver's applicable license agreements with MediaTek Inc.
- */
- /*
- * MTK PMIF Driver
- *
- * Copyright 2019 MediaTek Co.,Ltd.
- *
- * DESCRIPTION:
- * This file provides API for other drivers to access PMIC registers
- *
- */
- #include <pmif.h>
- #include <spmi.h>
- #include <pmif_sw.h>
- #include <spmi_sw.h>
- #define GET_SWINF_0_FSM(x) ((x>>1) & 0x00000007)
- #define GET_PMIF_INIT_DONE(x) ((x>>15) & 0x00000001)
- #define TIMEOUT_WAIT_IDLE (1000000) /* ap latency concern 1ms */
- static int pmif_spmi_read_cmd(struct pmif *arb, unsigned char opc,
- unsigned char sid, unsigned short addr, unsigned char *buf,
- unsigned short len);
- static int pmif_spmi_write_cmd(struct pmif *arb, unsigned char opc,
- unsigned char sid, unsigned short addr, const unsigned char *buf,
- unsigned short len);
- #if PMIF_NO_PMIC
- static int pmif_spmi_read_cmd(struct pmif *arb, unsigned char opc,
- unsigned char sid, unsigned short addr, unsigned char *buf,
- unsigned short len)
- {
- PMIF_INFO("do Nothing.\n");
- return 0;
- }
- static int pmif_spmi_write_cmd(struct pmif *arb, unsigned char opc,
- unsigned char sid, unsigned short addr, const unsigned char *buf,
- unsigned short len)
- {
- PMIF_INFO("do Nothing.\n");
- return 0;
- }
- /* init interface */
- int pmif_spmi_init(int mstid)
- {
- PMIF_INFO("do Nothing.\n");
- return 0;
- }
- #else /* #if PMIF_NO_PMIC */
- /* pmif internal API declaration */
- #if PMIF_TIMEOUT
- static unsigned long long pmif_get_current_time(void);
- static int pmif_timeout_ns(unsigned long long start_time_ns,
- unsigned long long timeout_time_ns);
- static unsigned long long pmif_time2ns(unsigned long long time_us);
- #endif
- enum pmif_regs {
- PMIF_INIT_DONE,
- PMIF_INF_EN,
- PMIF_INF_CMD_PER_0,
- PMIF_INF_CMD_PER_1,
- PMIF_INF_CMD_PER_2,
- PMIF_INF_CMD_PER_3,
- PMIF_INF_MAX_BYTECNT_PER_0,
- PMIF_INF_MAX_BYTECNT_PER_1,
- PMIF_INF_MAX_BYTECNT_PER_2,
- PMIF_INF_MAX_BYTECNT_PER_3,
- PMIF_ARB_EN,
- PMIF_LAT_CNTER_EN,
- PMIF_LAT_LIMIT_LOADING,
- PMIF_LAT_LIMIT_0,
- PMIF_LAT_LIMIT_1,
- PMIF_LAT_LIMIT_2,
- PMIF_LAT_LIMIT_3,
- PMIF_LAT_LIMIT_4,
- PMIF_LAT_LIMIT_5,
- PMIF_LAT_LIMIT_6,
- PMIF_LAT_LIMIT_7,
- PMIF_LAT_LIMIT_8,
- PMIF_LAT_LIMIT_9,
- PMIF_CMDISSUE_EN,
- PMIF_TIMER_CTRL,
- PMIF_SPI_MODE_CTRL,
- PMIF_IRQ_EVENT_EN_0,
- PMIF_IRQ_FLAG_0,
- PMIF_IRQ_CLR_0,
- PMIF_SWINF_0_ACC,
- PMIF_SWINF_0_WDATA_31_0,
- PMIF_SWINF_0_WDATA_63_32,
- PMIF_SWINF_0_RDATA_31_0,
- PMIF_SWINF_0_RDATA_63_32,
- PMIF_SWINF_0_VLD_CLR,
- PMIF_SWINF_0_STA,
- PMIF_SWINF_1_ACC,
- PMIF_SWINF_1_WDATA_31_0,
- PMIF_SWINF_1_WDATA_63_32,
- PMIF_SWINF_1_RDATA_31_0,
- PMIF_SWINF_1_RDATA_63_32,
- PMIF_SWINF_1_VLD_CLR,
- PMIF_SWINF_1_STA,
- PMIF_SWINF_2_ACC,
- PMIF_SWINF_2_WDATA_31_0,
- PMIF_SWINF_2_WDATA_63_32,
- PMIF_SWINF_2_RDATA_31_0,
- PMIF_SWINF_2_RDATA_63_32,
- PMIF_SWINF_2_VLD_CLR,
- PMIF_SWINF_2_STA,
- PMIF_SWINF_3_ACC,
- PMIF_SWINF_3_WDATA_31_0,
- PMIF_SWINF_3_WDATA_63_32,
- PMIF_SWINF_3_RDATA_31_0,
- PMIF_SWINF_3_RDATA_63_32,
- PMIF_SWINF_3_VLD_CLR,
- PMIF_SWINF_3_STA,
- };
- static int mt6xxx_regs[] = {
- [PMIF_INIT_DONE] = 0x0000,
- [PMIF_INF_EN] = 0x0024,
- [PMIF_INF_CMD_PER_0] = 0x002c,
- [PMIF_INF_CMD_PER_1] = 0x0030,
- [PMIF_INF_CMD_PER_2] = 0x0034,
- [PMIF_INF_CMD_PER_3] = 0x0038,
- [PMIF_INF_MAX_BYTECNT_PER_0] = 0x003c,
- [PMIF_INF_MAX_BYTECNT_PER_1] = 0x0040,
- [PMIF_INF_MAX_BYTECNT_PER_2] = 0x0044,
- [PMIF_INF_MAX_BYTECNT_PER_3] = 0x0048,
- [PMIF_ARB_EN] = 0x0150,
- [PMIF_LAT_CNTER_EN] = 0x01DC,
- [PMIF_LAT_LIMIT_LOADING] = 0x01E0,
- [PMIF_LAT_LIMIT_0] = 0x01E4,
- [PMIF_LAT_LIMIT_1] = 0x01E8,
- [PMIF_LAT_LIMIT_2] = 0x01EC,
- [PMIF_LAT_LIMIT_3] = 0x01F0,
- [PMIF_LAT_LIMIT_4] = 0x01F4,
- [PMIF_LAT_LIMIT_5] = 0x01F8,
- [PMIF_LAT_LIMIT_6] = 0x01FC,
- [PMIF_LAT_LIMIT_7] = 0x0200,
- [PMIF_LAT_LIMIT_8] = 0x0204,
- [PMIF_LAT_LIMIT_9] = 0x0208,
- [PMIF_CMDISSUE_EN] = 0x03B4,
- [PMIF_TIMER_CTRL] = 0x03E0,
- [PMIF_SPI_MODE_CTRL] = 0x0400,
- [PMIF_IRQ_EVENT_EN_0] = 0x0418,
- [PMIF_IRQ_FLAG_0] = 0x0420,
- [PMIF_IRQ_CLR_0] = 0x0424,
- [PMIF_SWINF_0_ACC] = 0x0C00,
- [PMIF_SWINF_0_WDATA_31_0] = 0x0C04,
- [PMIF_SWINF_0_WDATA_63_32] = 0x0C08,
- [PMIF_SWINF_0_RDATA_31_0] = 0x0C14,
- [PMIF_SWINF_0_RDATA_63_32] = 0x0C18,
- [PMIF_SWINF_0_VLD_CLR] = 0x0C24,
- [PMIF_SWINF_0_STA] = 0x0C28,
- [PMIF_SWINF_1_ACC] = 0x0C40,
- [PMIF_SWINF_1_WDATA_31_0] = 0x0C44,
- [PMIF_SWINF_1_WDATA_63_32] = 0x0C48,
- [PMIF_SWINF_1_RDATA_31_0] = 0x0C54,
- [PMIF_SWINF_1_RDATA_63_32] = 0x0C58,
- [PMIF_SWINF_1_VLD_CLR] = 0x0C64,
- [PMIF_SWINF_1_STA] = 0x0C68,
- [PMIF_SWINF_2_ACC] = 0x0C80,
- [PMIF_SWINF_2_WDATA_31_0] = 0x0C84,
- [PMIF_SWINF_2_WDATA_63_32] = 0x0C88,
- [PMIF_SWINF_2_RDATA_31_0] = 0x0C94,
- [PMIF_SWINF_2_RDATA_63_32] = 0x0C98,
- [PMIF_SWINF_2_VLD_CLR] = 0x0CA4,
- [PMIF_SWINF_2_STA] = 0x0CA8,
- [PMIF_SWINF_3_ACC] = 0x0CC0,
- [PMIF_SWINF_3_WDATA_31_0] = 0x0CC4,
- [PMIF_SWINF_3_WDATA_63_32] = 0x0CC8,
- [PMIF_SWINF_3_RDATA_31_0] = 0x0CD4,
- [PMIF_SWINF_3_RDATA_63_32] = 0x0CD8,
- [PMIF_SWINF_3_VLD_CLR] = 0x0CE4,
- [PMIF_SWINF_3_STA] = 0x0CE8,
- };
- static struct pmif pmif_spmi_arb[] = {
- {
- .base = (unsigned int *)PMIF_SPMI_BASE,
- .regs = mt6xxx_regs,
- .swinf_ch_start = PMIF_SWINF_0_CHAN_NO,
- .swinf_no = PMIF_AP_SWINF_NO,
- .write = 0x0,
- .mstid = SPMI_MASTER_0,
- .pmifid = PMIF_PMIFID,
- .read_cmd = pmif_spmi_read_cmd,
- .write_cmd = pmif_spmi_write_cmd,
- .is_pmif_init_done = is_pmif_spmi_init_done,
- },
- };
- /* static struct pmif pmif_spi_arb[0]; */
- /* pmif timeout */
- #if PMIF_TIMEOUT
- static unsigned long long pmif_get_current_time(void)
- {
- return gpt4_get_current_tick();
- }
- static int pmif_timeout_ns(unsigned long long start_time_ns,
- unsigned long long timeout_time_ns)
- {
- return gpt4_timeout_tick(start_time_ns, timeout_time_ns);
- }
- static unsigned long long pmif_time2ns(unsigned long long time_us)
- {
- return gpt4_time2tick_us(time_us);
- }
- #else
- static unsigned long long pmif_get_current_time(void)
- {
- return 0;
- }
- static int pmif_timeout_ns(unsigned long long start_time_ns,
- unsigned long long elapse_time)
- {
- return 0;
- }
- static unsigned long long pmif_time2ns(unsigned long long time_us)
- {
- return 0;
- }
- #endif
- static inline unsigned int pmif_check_idle(int mstid) {
- struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
- unsigned int reg_rdata, offset = 0;
- #if PMIF_TIMEOUT
- unsigned long long start_time_ns = 0, end_time_ns = 0, timeout_ns = 0;
- unsigned long time_cnt = 100000;
- start_time_ns = pmif_get_current_time();
- timeout_ns = pmif_time2ns(TIMEOUT_WAIT_IDLE);
- #endif
- do {
- #if PMIF_TIMEOUT
- if (pmif_timeout_ns(start_time_ns, timeout_ns)) {
- end_time_ns = pmif_get_current_time();
- PMIF_ERR("%s timeout %d %d\n", __func__, start_time_ns,
- end_time_ns - start_time_ns);
- return -ETIMEDOUT;
- }
- if ((time_cnt--) == 0) {
- PMIF_ERR("%s timeout %d %d\n", __func__, start_time_ns,
- end_time_ns - start_time_ns);
- return -ETIMEDOUT;
- }
- #endif
- offset = arb->regs[PMIF_SWINF_0_STA] + (0x40 * arb->swinf_no);
- reg_rdata = DRV_Reg32(arb->base + offset);
- } while(GET_SWINF_0_FSM(reg_rdata) != SWINF_FSM_IDLE);
- return 0;
- }
- static inline unsigned int pmif_check_vldclr(int mstid) {
- struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
- unsigned int reg_rdata, offset = 0;
- #if PMIF_TIMEOUT
- unsigned long long start_time_ns = 0, end_time_ns = 0, timeout_ns = 0;
- unsigned long time_cnt = 100000;
- start_time_ns = pmif_get_current_time();
- timeout_ns = pmif_time2ns(TIMEOUT_WAIT_IDLE);
- #endif
- do {
- #if PMIF_TIMEOUT
- if (pmif_timeout_ns(start_time_ns, timeout_ns)) {
- end_time_ns = pmif_get_current_time();
- PMIF_ERR("%s timeout %d %d\n", __func__, start_time_ns,
- end_time_ns - start_time_ns);
- return -ETIMEDOUT;
- }
- if ((time_cnt--) == 0) {
- PMIF_ERR("%s timeout %d %d\n", __func__, start_time_ns,
- end_time_ns - start_time_ns);
- return -ETIMEDOUT;
- }
- #endif
- offset = arb->regs[PMIF_SWINF_0_STA] + (0x40 * arb->swinf_no);
- reg_rdata = DRV_Reg32(arb->base + offset);
- } while(GET_SWINF_0_FSM(reg_rdata) != SWINF_FSM_WFVLDCLR);
- return 0;
- }
- static int pmif_spmi_read_cmd(struct pmif *arb, unsigned char opc,
- unsigned char sid, unsigned short addr, unsigned char *buf,
- unsigned short len)
- {
- int write = 0x0;
- unsigned int ret = 0, offset = 0, data = 0;
- unsigned char bc = len - 1;
- if ((sid & ~(0xf)) != 0x0)
- return -EINVAL;
- if (len > PMIF_BYTECNT_MAX)
- return -EINVAL;
- if ((bc & ~(0x1)) != 0x0)
- return -EINVAL;
- /* Check the opcode */
- if (opc >= 0x60 && opc <= 0x7F)
- opc = PMIF_CMD_REG;
- else if (opc >= 0x20 && opc <= 0x2F)
- opc = PMIF_CMD_EXT_REG;
- else if (opc >= 0x38 && opc <= 0x3F)
- opc = PMIF_CMD_EXT_REG_LONG;
- else
- return -EINVAL;
- ENTER_CRITICAL();
- /* Wait for Software Interface FSM state to be IDLE. */
- ret = pmif_check_idle(arb->mstid);
- if(ret)
- return ret;
- /* Send the command. */
- offset = arb->regs[PMIF_SWINF_0_ACC] + (0x40 * arb->swinf_no);
- DRV_WriteReg32(arb->base + offset,
- ((unsigned)opc << 30) | (write << 29) | (sid << 24) | (bc << 16) | addr);
- /* Wait for Software Interface FSM state to be WFVLDCLR,
- *
- * read the data and clear the valid flag.
- */
- if(write == 0)
- {
- ret = pmif_check_vldclr(arb->mstid);
- if(ret)
- return ret;
- offset =
- arb->regs[PMIF_SWINF_0_RDATA_31_0] + (0x40 * arb->swinf_no);
- data = DRV_Reg32(arb->base + offset);
- memcpy(buf, &data, (bc & 3) + 1);
- offset =
- arb->regs[PMIF_SWINF_0_VLD_CLR] + (0x40 * arb->swinf_no);
- DRV_WriteReg32(arb->base + offset, 0x1);
- }
- EXIT_CRITICAL();
- return 0x0;
- }
- static int pmif_spmi_write_cmd(struct pmif *arb, unsigned char opc,
- unsigned char sid, unsigned short addr, const unsigned char *buf,
- unsigned short len)
- {
- int write = 0x1;
- unsigned int ret = 0, offset = 0, data = 0;
- unsigned char bc = len - 1;
- if ((sid & ~(0xf)) != 0x0)
- return -EINVAL;
- if (len > PMIF_BYTECNT_MAX)
- return -EINVAL;
- if ((bc & ~(0x1)) != 0x0)
- return -EINVAL;
- /* Check the opcode */
- if (opc >= 0x40 && opc <= 0x5F)
- opc = PMIF_CMD_REG;
- else if (opc <= 0x0F)
- opc = PMIF_CMD_EXT_REG;
- else if (opc >= 0x30 && opc <= 0x37)
- opc = PMIF_CMD_EXT_REG_LONG;
- else if (opc >= 0x80)
- opc = PMIF_CMD_REG_0;
- else
- return -EINVAL;
- ENTER_CRITICAL();
- /* Wait for Software Interface FSM state to be IDLE. */
- ret = pmif_check_idle(arb->mstid);
- if(ret)
- return ret;
- /* Set the write data. */
- if (write == 1)
- {
- offset =
- arb->regs[PMIF_SWINF_0_WDATA_31_0] + (0x40 * arb->swinf_no);
- memcpy(&data, buf, (bc & 3) + 1);
- DRV_WriteReg32(arb->base + offset, data);
- }
- /* Send the command. */
- offset = arb->regs[PMIF_SWINF_0_ACC] + (0x40 * arb->swinf_no);
- DRV_WriteReg32(arb->base + offset,
- ((unsigned)opc << 30) | (write << 29) | (sid << 24) |
- (bc << 16) | addr);
- EXIT_CRITICAL();
- return 0x0;
- }
- struct pmif *get_pmif_controller(int inf, int mstid)
- {
- if (inf == PMIF_SPMI) {
- return &pmif_spmi_arb[mstid];
- } else if (inf == PMIF_SPI) {
- /* TBD
- *pmif_spi_arb[mstid].base = (unsigned int *)PMIF_SPI_BASE;
- *pmif_spi_arb[mstid].swinf_no = 0x0;
- *pmif_spi_arb[mstid].write = 0x0;
- *pmif_spi_arb[mstid].pmifid = 0x0;
- *pmif_spi_arb[mstid].read_cmd = pmif_spi_read_cmd;
- *pmif_spi_arb[mstid].write_cmd = pmif_spi_write_cmd;
- *pmif_spi_arb[mstid].read_cmd_nochk = pmif_spi_read_cmd_nochk;
- *pmif_spi_arb[mstid].write_cmd_nochk =
- * pmif_spi_write_cmd_nochk;
- *return &pmif_spi_arb[mstid];
- */
- }
- return 0;
- }
- int is_pmif_spmi_init_done(int mstid)
- {
- int ret = 0;
- struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
- ret = DRV_Reg32(arb->base + arb->regs[PMIF_INIT_DONE]);
- PMIF_INFO("%s ret = %d\n", __func__, ret);
- if ((ret & 0x1) == 1)
- return 0;
- return -ENODEV;
- }
- int pmif_spmi_init(int mstid)
- {
- struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
- int ret = 0;
- INIT_CRITICAL();
- ret = arb->is_pmif_init_done(mstid);
- if(ret) {
- PMIF_ERR("init done check fail\n");
- return -ENODEV;
- }
- ret = spmi_init(arb);
- if(ret) {
- PMIF_ERR("init fail\n");
- return -ENODEV;
- }
- return 0;
- }
- #endif /* endif PMIF_NO_PMIC */
|