summaryrefslogtreecommitdiff
path: root/drivers/power/qcom-charger/fg-memif.c
diff options
context:
space:
mode:
authorNicholas Troast <ntroast@codeaurora.org>2017-01-10 09:56:57 -0800
committerNicholas Troast <ntroast@codeaurora.org>2017-01-17 12:21:07 -0800
commitd4b9ff94dff74035e465eb341036b79e30ac3d14 (patch)
tree98db6ac604de4b255d7aeaefca29753d349f7855 /drivers/power/qcom-charger/fg-memif.c
parentcbd28f4381c058201f645427771f3205b641bb4b (diff)
power: align qcom drivers with msm-4.9 kernel
The power directory structure has changed in kernel version 4.9. Align msm-4.4 with this new directory structure. Change-Id: Iba729f8ef33245ea78cdc05276ba8f5593191509 Signed-off-by: Nicholas Troast <ntroast@codeaurora.org>
Diffstat (limited to 'drivers/power/qcom-charger/fg-memif.c')
-rw-r--r--drivers/power/qcom-charger/fg-memif.c704
1 files changed, 0 insertions, 704 deletions
diff --git a/drivers/power/qcom-charger/fg-memif.c b/drivers/power/qcom-charger/fg-memif.c
deleted file mode 100644
index a98ff7d765e3..000000000000
--- a/drivers/power/qcom-charger/fg-memif.c
+++ /dev/null
@@ -1,704 +0,0 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#define pr_fmt(fmt) "FG: %s: " fmt, __func__
-
-#include "fg-core.h"
-#include "fg-reg.h"
-
-/* Generic definitions */
-#define RETRY_COUNT 3
-#define BYTES_PER_SRAM_WORD 4
-
-enum {
- FG_READ = 0,
- FG_WRITE,
-};
-
-static int fg_set_address(struct fg_chip *chip, u16 address)
-{
- u8 buffer[2];
- int rc;
-
- buffer[0] = address & 0xFF;
- /* MSB has to be written zero */
- buffer[1] = 0;
-
- rc = fg_write(chip, MEM_IF_ADDR_LSB(chip), buffer, 2);
- if (rc < 0) {
- pr_err("failed to write to 0x%04X, rc=%d\n",
- MEM_IF_ADDR_LSB(chip), rc);
- return rc;
- }
-
- return rc;
-}
-
-static int fg_config_access_mode(struct fg_chip *chip, bool access, bool burst)
-{
- int rc;
- u8 intf_ctl = 0;
-
- intf_ctl = ((access == FG_WRITE) ? IMA_WR_EN_BIT : 0) |
- (burst ? MEM_ACS_BURST_BIT : 0);
-
- rc = fg_masked_write(chip, MEM_IF_IMA_CTL(chip), IMA_CTL_MASK,
- intf_ctl);
- if (rc < 0) {
- pr_err("failed to write to 0x%04x, rc=%d\n",
- MEM_IF_IMA_CTL(chip), rc);
- return -EIO;
- }
-
- return rc;
-}
-
-static int fg_run_iacs_clear_sequence(struct fg_chip *chip)
-{
- u8 val, hw_sts, exp_sts;
- int rc, tries = 250;
-
- /*
- * Values to write for running IACS clear sequence comes from
- * hardware documentation.
- */
- rc = fg_masked_write(chip, MEM_IF_IMA_CFG(chip),
- IACS_CLR_BIT | STATIC_CLK_EN_BIT,
- IACS_CLR_BIT | STATIC_CLK_EN_BIT);
- if (rc < 0) {
- pr_err("failed to write 0x%04x, rc=%d\n", MEM_IF_IMA_CFG(chip),
- rc);
- return rc;
- }
-
- rc = fg_config_access_mode(chip, FG_READ, false);
- if (rc < 0) {
- pr_err("failed to write to 0x%04x, rc=%d\n",
- MEM_IF_IMA_CTL(chip), rc);
- return rc;
- }
-
- rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip),
- MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT,
- MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT);
- if (rc < 0) {
- pr_err("failed to set ima_req_access bit rc=%d\n", rc);
- return rc;
- }
-
- /* Delay for the clock to reach FG */
- usleep_range(35, 40);
-
- while (1) {
- val = 0;
- rc = fg_write(chip, MEM_IF_ADDR_MSB(chip), &val, 1);
- if (rc < 0) {
- pr_err("failed to write 0x%04x, rc=%d\n",
- MEM_IF_ADDR_MSB(chip), rc);
- return rc;
- }
-
- val = 0;
- rc = fg_write(chip, MEM_IF_WR_DATA3(chip), &val, 1);
- if (rc < 0) {
- pr_err("failed to write 0x%04x, rc=%d\n",
- MEM_IF_WR_DATA3(chip), rc);
- return rc;
- }
-
- rc = fg_read(chip, MEM_IF_RD_DATA3(chip), &val, 1);
- if (rc < 0) {
- pr_err("failed to read 0x%04x, rc=%d\n",
- MEM_IF_RD_DATA3(chip), rc);
- return rc;
- }
-
- /* Delay for IMA hardware to clear */
- usleep_range(35, 40);
-
- rc = fg_read(chip, MEM_IF_IMA_HW_STS(chip), &hw_sts, 1);
- if (rc < 0) {
- pr_err("failed to read ima_hw_sts rc=%d\n", rc);
- return rc;
- }
-
- if (hw_sts != 0)
- continue;
-
- rc = fg_read(chip, MEM_IF_IMA_EXP_STS(chip), &exp_sts, 1);
- if (rc < 0) {
- pr_err("failed to read ima_exp_sts rc=%d\n", rc);
- return rc;
- }
-
- if (exp_sts == 0 || !(--tries))
- break;
- }
-
- if (!tries)
- pr_err("Failed to clear the error? hw_sts: %x exp_sts: %d\n",
- hw_sts, exp_sts);
-
- rc = fg_masked_write(chip, MEM_IF_IMA_CFG(chip), IACS_CLR_BIT, 0);
- if (rc < 0) {
- pr_err("failed to write 0x%04x, rc=%d\n", MEM_IF_IMA_CFG(chip),
- rc);
- return rc;
- }
-
- udelay(5);
-
- rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip),
- MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT, 0);
- if (rc < 0) {
- pr_err("failed to write to 0x%04x, rc=%d\n",
- MEM_IF_MEM_INTF_CFG(chip), rc);
- return rc;
- }
-
- /* Delay before next transaction is attempted */
- usleep_range(35, 40);
- fg_dbg(chip, FG_SRAM_READ | FG_SRAM_WRITE, "IACS clear sequence complete\n");
- return rc;
-}
-
-int fg_clear_dma_errors_if_any(struct fg_chip *chip)
-{
- int rc;
- u8 dma_sts;
-
- rc = fg_read(chip, MEM_IF_DMA_STS(chip), &dma_sts, 1);
- if (rc < 0) {
- pr_err("failed to read addr=0x%04x, rc=%d\n",
- MEM_IF_DMA_STS(chip), rc);
- return rc;
- }
- fg_dbg(chip, FG_STATUS, "dma_sts: %x\n", dma_sts);
-
- if (dma_sts & (DMA_WRITE_ERROR_BIT | DMA_READ_ERROR_BIT)) {
- rc = fg_masked_write(chip, MEM_IF_DMA_CTL(chip),
- DMA_CLEAR_LOG_BIT, DMA_CLEAR_LOG_BIT);
- if (rc < 0) {
- pr_err("failed to write addr=0x%04x, rc=%d\n",
- MEM_IF_DMA_CTL(chip), rc);
- return rc;
- }
- }
-
- return 0;
-}
-
-int fg_clear_ima_errors_if_any(struct fg_chip *chip, bool check_hw_sts)
-{
- int rc = 0;
- u8 err_sts, exp_sts = 0, hw_sts = 0;
- bool run_err_clr_seq = false;
-
- rc = fg_read(chip, MEM_IF_IMA_EXP_STS(chip), &exp_sts, 1);
- if (rc < 0) {
- pr_err("failed to read ima_exp_sts rc=%d\n", rc);
- return rc;
- }
-
- rc = fg_read(chip, MEM_IF_IMA_HW_STS(chip), &hw_sts, 1);
- if (rc < 0) {
- pr_err("failed to read ima_hw_sts rc=%d\n", rc);
- return rc;
- }
-
- rc = fg_read(chip, MEM_IF_IMA_ERR_STS(chip), &err_sts, 1);
- if (rc < 0) {
- pr_err("failed to read ima_err_sts rc=%d\n", rc);
- return rc;
- }
-
- fg_dbg(chip, FG_SRAM_READ | FG_SRAM_WRITE, "ima_err_sts=%x ima_exp_sts=%x ima_hw_sts=%x\n",
- err_sts, exp_sts, hw_sts);
-
- if (check_hw_sts) {
- /*
- * Lower nibble should be equal to upper nibble before SRAM
- * transactions begins from SW side. If they are unequal, then
- * the error clear sequence should be run irrespective of IMA
- * exception errors.
- */
- if ((hw_sts & 0x0F) != hw_sts >> 4) {
- pr_err("IMA HW not in correct state, hw_sts=%x\n",
- hw_sts);
- run_err_clr_seq = true;
- }
- }
-
- if (exp_sts & (IACS_ERR_BIT | XCT_TYPE_ERR_BIT | DATA_RD_ERR_BIT |
- DATA_WR_ERR_BIT | ADDR_BURST_WRAP_BIT | ADDR_STABLE_ERR_BIT)) {
- pr_err("IMA exception bit set, exp_sts=%x\n", exp_sts);
- run_err_clr_seq = true;
- }
-
- if (run_err_clr_seq) {
- /* clear the error */
- rc = fg_run_iacs_clear_sequence(chip);
- if (rc < 0) {
- pr_err("failed to run iacs clear sequence rc=%d\n", rc);
- return rc;
- }
-
- /* Retry again as there was an error in the transaction */
- return -EAGAIN;
- }
-
- return rc;
-}
-
-static int fg_check_iacs_ready(struct fg_chip *chip)
-{
- int rc = 0, tries = 250;
- u8 ima_opr_sts = 0;
-
- /*
- * Additional delay to make sure IACS ready bit is set after
- * Read/Write operation.
- */
-
- usleep_range(30, 35);
- while (1) {
- rc = fg_read(chip, MEM_IF_IMA_OPR_STS(chip), &ima_opr_sts, 1);
- if (rc < 0) {
- pr_err("failed to read 0x%04x, rc=%d\n",
- MEM_IF_IMA_OPR_STS(chip), rc);
- return rc;
- }
-
- if (ima_opr_sts & IACS_RDY_BIT)
- break;
-
- if (!(--tries))
- break;
-
- /* delay for iacs_ready to be asserted */
- usleep_range(5000, 7000);
- }
-
- if (!tries) {
- pr_err("IACS_RDY not set\n");
- /* check for error condition */
- rc = fg_clear_ima_errors_if_any(chip, false);
- if (rc < 0) {
- pr_err("Failed to check for ima errors rc=%d\n", rc);
- return rc;
- }
-
- return -EBUSY;
- }
-
- return 0;
-}
-
-static int __fg_interleaved_mem_write(struct fg_chip *chip, u16 address,
- int offset, u8 *val, int len)
-{
- int rc = 0, i;
- u8 *ptr = val, byte_enable = 0, num_bytes = 0;
-
- fg_dbg(chip, FG_SRAM_WRITE, "length %d addr=%02X offset=%d\n", len,
- address, offset);
-
- while (len > 0) {
- num_bytes = (offset + len) > BYTES_PER_SRAM_WORD ?
- (BYTES_PER_SRAM_WORD - offset) : len;
-
- /* write to byte_enable */
- for (i = offset; i < (offset + num_bytes); i++)
- byte_enable |= BIT(i);
-
- rc = fg_write(chip, MEM_IF_IMA_BYTE_EN(chip), &byte_enable, 1);
- if (rc < 0) {
- pr_err("Unable to write to byte_en_reg rc=%d\n",
- rc);
- return rc;
- }
-
- /* write data */
- rc = fg_write(chip, MEM_IF_WR_DATA0(chip) + offset, ptr,
- num_bytes);
- if (rc < 0) {
- pr_err("failed to write to 0x%04x, rc=%d\n",
- MEM_IF_WR_DATA0(chip) + offset, rc);
- return rc;
- }
-
- /*
- * The last-byte WR_DATA3 starts the write transaction.
- * Write a dummy value to WR_DATA3 if it does not have
- * valid data. This dummy data is not written to the
- * SRAM as byte_en for WR_DATA3 is not set.
- */
- if (!(byte_enable & BIT(3))) {
- u8 dummy_byte = 0x0;
-
- rc = fg_write(chip, MEM_IF_WR_DATA3(chip), &dummy_byte,
- 1);
- if (rc < 0) {
- pr_err("failed to write dummy-data to WR_DATA3 rc=%d\n",
- rc);
- return rc;
- }
- }
-
- /* check for error condition */
- rc = fg_clear_ima_errors_if_any(chip, false);
- if (rc < 0) {
- pr_err("Failed to check for ima errors rc=%d\n", rc);
- return rc;
- }
-
- ptr += num_bytes;
- len -= num_bytes;
- offset = byte_enable = 0;
-
- rc = fg_check_iacs_ready(chip);
- if (rc < 0) {
- pr_debug("IACS_RDY failed rc=%d\n", rc);
- return rc;
- }
- }
-
- return rc;
-}
-
-static int __fg_interleaved_mem_read(struct fg_chip *chip, u16 address,
- int offset, u8 *val, int len)
-{
- int rc = 0, total_len;
- u8 *rd_data = val, num_bytes;
- char str[DEBUG_PRINT_BUFFER_SIZE];
-
- fg_dbg(chip, FG_SRAM_READ, "length %d addr=%02X\n", len, address);
-
- total_len = len;
- while (len > 0) {
- num_bytes = (offset + len) > BYTES_PER_SRAM_WORD ?
- (BYTES_PER_SRAM_WORD - offset) : len;
- rc = fg_read(chip, MEM_IF_RD_DATA0(chip) + offset, rd_data,
- num_bytes);
- if (rc < 0) {
- pr_err("failed to read 0x%04x, rc=%d\n",
- MEM_IF_RD_DATA0(chip) + offset, rc);
- return rc;
- }
-
- rd_data += num_bytes;
- len -= num_bytes;
- offset = 0;
-
- /* check for error condition */
- rc = fg_clear_ima_errors_if_any(chip, false);
- if (rc < 0) {
- pr_err("Failed to check for ima errors rc=%d\n", rc);
- return rc;
- }
-
- if (len && len < BYTES_PER_SRAM_WORD) {
- /*
- * Move to single mode. Changing address is not
- * required here as it must be in burst mode. Address
- * will get incremented internally by FG HW once the MSB
- * of RD_DATA is read.
- */
- rc = fg_config_access_mode(chip, FG_READ, 0);
- if (rc < 0) {
- pr_err("failed to move to single mode rc=%d\n",
- rc);
- return -EIO;
- }
- }
-
- rc = fg_check_iacs_ready(chip);
- if (rc < 0) {
- pr_debug("IACS_RDY failed rc=%d\n", rc);
- return rc;
- }
- }
-
- if (*chip->debug_mask & FG_SRAM_READ) {
- fill_string(str, DEBUG_PRINT_BUFFER_SIZE, val, total_len);
- pr_info("data read: %s\n", str);
- }
-
- return rc;
-}
-
-static int fg_get_mem_access_status(struct fg_chip *chip, bool *status)
-{
- int rc;
- u8 mem_if_sts;
-
- rc = fg_read(chip, MEM_IF_MEM_INTF_CFG(chip), &mem_if_sts, 1);
- if (rc < 0) {
- pr_err("failed to read rif_mem status rc=%d\n", rc);
- return rc;
- }
-
- *status = mem_if_sts & MEM_ACCESS_REQ_BIT;
- return 0;
-}
-
-static bool is_mem_access_available(struct fg_chip *chip, int access)
-{
- bool rif_mem_sts = true;
- int rc, time_count = 0;
-
- while (1) {
- rc = fg_get_mem_access_status(chip, &rif_mem_sts);
- if (rc < 0)
- return rc;
-
- /* This is an inverting logic */
- if (!rif_mem_sts)
- break;
-
- fg_dbg(chip, FG_SRAM_READ | FG_SRAM_WRITE, "MEM_ACCESS_REQ is not clear yet for IMA_%s\n",
- access ? "write" : "read");
-
- /*
- * Try this no more than 4 times. If MEM_ACCESS_REQ is not
- * clear, then return an error instead of waiting for it again.
- */
- if (time_count > 4) {
- pr_err("Tried 4 times(~16ms) polling MEM_ACCESS_REQ\n");
- return false;
- }
-
- /* Wait for 4ms before reading MEM_ACCESS_REQ again */
- usleep_range(4000, 4100);
- time_count++;
- }
- return true;
-}
-
-static int fg_interleaved_mem_config(struct fg_chip *chip, u8 *val,
- u16 address, int offset, int len, bool access)
-{
- int rc = 0;
-
- if (!is_mem_access_available(chip, access))
- return -EBUSY;
-
- /* configure for IMA access */
- rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip),
- MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT,
- MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT);
- if (rc < 0) {
- pr_err("failed to set ima_req_access bit rc=%d\n", rc);
- return rc;
- }
-
- /* configure for the read/write, single/burst mode */
- rc = fg_config_access_mode(chip, access, (offset + len) > 4);
- if (rc < 0) {
- pr_err("failed to set memory access rc = %d\n", rc);
- return rc;
- }
-
- rc = fg_check_iacs_ready(chip);
- if (rc < 0) {
- pr_err_ratelimited("IACS_RDY failed rc=%d\n", rc);
- return rc;
- }
-
- rc = fg_set_address(chip, address);
- if (rc < 0) {
- pr_err("failed to set address rc = %d\n", rc);
- return rc;
- }
-
- if (access == FG_READ) {
- rc = fg_check_iacs_ready(chip);
- if (rc < 0) {
- pr_debug("IACS_RDY failed rc=%d\n", rc);
- return rc;
- }
- }
-
- return rc;
-}
-
-static int fg_get_beat_count(struct fg_chip *chip, u8 *count)
-{
- int rc;
-
- rc = fg_read(chip, MEM_IF_FG_BEAT_COUNT(chip), count, 1);
- *count &= BEAT_COUNT_MASK;
- return rc;
-}
-
-int fg_interleaved_mem_read(struct fg_chip *chip, u16 address, u8 offset,
- u8 *val, int len)
-{
- int rc = 0;
- u8 start_beat_count, end_beat_count, count = 0;
- bool retry_once = false;
-
- if (offset > 3) {
- pr_err("offset too large %d\n", offset);
- return -EINVAL;
- }
-
-retry:
- rc = fg_interleaved_mem_config(chip, val, address, offset, len,
- FG_READ);
- if (rc < 0) {
- pr_err("failed to configure SRAM for IMA rc = %d\n", rc);
- goto out;
- }
-
- /* read the start beat count */
- rc = fg_get_beat_count(chip, &start_beat_count);
- if (rc < 0) {
- pr_err("failed to read beat count rc=%d\n", rc);
- goto out;
- }
-
- /* read data */
- rc = __fg_interleaved_mem_read(chip, address, offset, val, len);
- if (rc < 0) {
- if ((rc == -EAGAIN) && (count < RETRY_COUNT)) {
- count++;
- pr_err("IMA access failed retry_count = %d\n", count);
- goto retry;
- }
- pr_err("failed to read SRAM address rc = %d\n", rc);
- goto out;
- }
-
- /* read the end beat count */
- rc = fg_get_beat_count(chip, &end_beat_count);
- if (rc < 0) {
- pr_err("failed to read beat count rc=%d\n", rc);
- goto out;
- }
-
- fg_dbg(chip, FG_SRAM_READ, "Start beat_count = %x End beat_count = %x\n",
- start_beat_count, end_beat_count);
-
- if (start_beat_count != end_beat_count && !retry_once) {
- fg_dbg(chip, FG_SRAM_READ, "Beat count(%d/%d) do not match - retry transaction\n",
- start_beat_count, end_beat_count);
- retry_once = true;
- }
-out:
- /* Release IMA access */
- rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip),
- MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT, 0);
- if (rc < 0) {
- pr_err("failed to reset IMA access bit rc = %d\n", rc);
- return rc;
- }
-
- if (retry_once) {
- retry_once = false;
- goto retry;
- }
-
- return rc;
-}
-
-int fg_interleaved_mem_write(struct fg_chip *chip, u16 address, u8 offset,
- u8 *val, int len, bool atomic_access)
-{
- int rc = 0;
- u8 start_beat_count, end_beat_count, count = 0;
-
- if (offset > 3) {
- pr_err("offset too large %d\n", offset);
- return -EINVAL;
- }
-
-retry:
- rc = fg_interleaved_mem_config(chip, val, address, offset, len,
- FG_WRITE);
- if (rc < 0) {
- pr_err("failed to configure SRAM for IMA rc = %d\n", rc);
- goto out;
- }
-
- /* read the start beat count */
- rc = fg_get_beat_count(chip, &start_beat_count);
- if (rc < 0) {
- pr_err("failed to read beat count rc=%d\n", rc);
- goto out;
- }
-
- /* write data */
- rc = __fg_interleaved_mem_write(chip, address, offset, val, len);
- if (rc < 0) {
- if ((rc == -EAGAIN) && (count < RETRY_COUNT)) {
- count++;
- pr_err("IMA access failed retry_count = %d\n", count);
- goto retry;
- }
- pr_err("failed to write SRAM address rc = %d\n", rc);
- goto out;
- }
-
- /* read the end beat count */
- rc = fg_get_beat_count(chip, &end_beat_count);
- if (rc < 0) {
- pr_err("failed to read beat count rc=%d\n", rc);
- goto out;
- }
-
- if (atomic_access && start_beat_count != end_beat_count)
- pr_err("Start beat_count = %x End beat_count = %x\n",
- start_beat_count, end_beat_count);
-out:
- /* Release IMA access */
- rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip),
- MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT, 0);
- if (rc < 0)
- pr_err("failed to reset IMA access bit rc = %d\n", rc);
-
- return rc;
-}
-
-int fg_ima_init(struct fg_chip *chip)
-{
- int rc;
-
- /*
- * Change the FG_MEM_INT interrupt to track IACS_READY
- * condition instead of end-of-transaction. This makes sure
- * that the next transaction starts only after the hw is ready.
- */
- rc = fg_masked_write(chip, MEM_IF_IMA_CFG(chip), IACS_INTR_SRC_SLCT_BIT,
- IACS_INTR_SRC_SLCT_BIT);
- if (rc < 0) {
- pr_err("failed to configure interrupt source %d\n", rc);
- return rc;
- }
-
- /* Clear DMA errors if any before clearing IMA errors */
- rc = fg_clear_dma_errors_if_any(chip);
- if (rc < 0) {
- pr_err("Error in checking DMA errors rc:%d\n", rc);
- return rc;
- }
-
- /* Clear IMA errors if any before SRAM transactions can begin */
- rc = fg_clear_ima_errors_if_any(chip, true);
- if (rc < 0 && rc != -EAGAIN) {
- pr_err("Error in checking IMA errors rc:%d\n", rc);
- return rc;
- }
-
- return 0;
-}