blob: 4fcd2384302083b8f24ca6010f2231e70498fe47 [file] [log] [blame]
Parth Dixitba68b552015-09-16 11:46:55 +05301/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
2
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation, nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28#include <pm_fg_sram.h>
29#include <pm8x41.h>
30#include <pm8x41_hw.h>
31#include <debug.h>
32#include <bits.h>
33#include <platform/timer.h>
34#include <pm_comm.h>
35
36static int fg_check_addr_mask(int sid,uint32_t addr,uint8_t mask,uint8_t set)
37{
38 uint8_t value;
39 int ret = 1;
40 int try = FG_MAX_TRY;
41
42 udelay(30);
43 while(try)
44 {
45 ret = pm_comm_read_byte_mask(sid, addr, mask, &value, 0);
46 if( !ret && (value == set) )
47 goto err;
48
49 udelay(1000);
50 try--;
51 }
52err:
53 return ret;
54}
55
56int pmi_fg_sram_read(uint32_t addr, uint32_t *data,int sid, uint8_t offset, uint8_t len)
57{
58 uint8_t value;
59 int err = 0;
60 uint8_t start_beat_count, end_beat_count;
61
62 if(offset > 3)
63 {
64 dprintf(INFO,"offset beyond the 4 byte boundary\n");
65 goto err;
66 }
67 /* poll to check if fg memif is available */
68 err = fg_check_addr_mask(sid,FG_MEMIF_MEM_INTF_CFG, RIF_MEM_ACCESS_REQ, 0);
69 if(err)
70 {
71 dprintf(INFO,"Failed to get fg sram access\n");
72 goto err;
73 }
74
75 /* enter into ima mode write 8'hA0 */
76 pm_comm_write_byte(sid, FG_MEMIF_MEM_INTF_CFG, 0xA0, 0);
77 /* ensure single read access 8'h00 */
78 pm_comm_write_byte(sid, FG_MEMIF_MEM_INTF_CTL, 0x00, 0);
79
80 /* poll ima is ready */
81 err = fg_check_addr_mask(sid, FG_MEMIF_IMA_OPERATION_STS, IACS_RDY, 1);
82 if(err)
83 {
84 dprintf(INFO,"IACS is not ready cannot enter ima mode\n");
85 goto err;
86 }
87
88 /* write lsb address of the requested data */
89 value = addr & 0xff;
90 pm_comm_write_byte(sid, FG_MEMIF_MEM_INTF_ADDR_LSB, value, 0);
91
92 /* write msb address of the requested data */
93 value = (addr >> 8) & 0xff;
94 pm_comm_write_byte(sid, FG_MEMIF_MEM_INTF_ADDR_MSB, value, 0);
95
96 /* poll until transaction is completed */
97 /* poll ima is ready */
98 err = fg_check_addr_mask(sid, FG_MEMIF_IMA_OPERATION_STS, IACS_RDY, 1);
99 if(err)
100 {
101 dprintf(INFO,"IACS is not ready cannot set address\n");
102 goto err;
103 }
104
105 /* read start beat count */
106 pm_comm_read_byte_mask(sid, FG_MEMIF_FG_BEAT_COUNT, BEAT_COUNT_MASK, &start_beat_count, 0);
107 /* read the data */
108 pm_comm_read_byte(sid, FG_MEMIF_MEM_INTF_RD_DATA0, &value, 0);
109 *data = value;
110 pm_comm_read_byte(sid, FG_MEMIF_MEM_INTF_RD_DATA1, &value, 0);
111 *data |= value << 8;
112 pm_comm_read_byte(sid, FG_MEMIF_MEM_INTF_RD_DATA2, &value, 0);
113 *data |= value << 16;
114 pm_comm_read_byte(sid, FG_MEMIF_MEM_INTF_RD_DATA3, &value, 0);
Umang Chheda8b25afe2020-03-19 11:27:20 +0530115 *data |= value << 24;
Parth Dixitba68b552015-09-16 11:46:55 +0530116
117 /* poll to check there was no error */
118 err = fg_check_addr_mask(sid, FG_MEMIF_IMA_OPERATION_STS, IACS_RDY, 1);
119 if(err)
120 {
121 dprintf(INFO,"IACS is not ready cannot read\n");
122 goto err;
123 }
124
125 pm_comm_read_byte(sid, FG_MEMIF_IMA_EXCEPTION_STS, &value, 0);
126 err = value;
127 if(!err)
128 {
129 *data = ((*data) >> (offset*8)) & (FG_DATA_MASK >> ((FG_DATA_MAX_LEN - len)*8) );
130 pm_comm_read_byte_mask(sid, FG_MEMIF_FG_BEAT_COUNT, BEAT_COUNT_MASK, &end_beat_count, 0);
131 if(start_beat_count != end_beat_count)
132 err = 1;
133 }
134 else
135 {
136 /* error occured */
137 /*perform iacs clear sequence 1'b1 */
138 pm_comm_read_byte(sid, FG_MEMIF_IMA_CFG, &value, 0);
139 value |= IACS_CLR;
140 pm_comm_write_byte(sid, FG_MEMIF_IMA_CFG, value, 0);
141 /* 8'h04 */
142 pm_comm_write_byte(sid, FG_MEMIF_MEM_INTF_ADDR_MSB, 0x04, 0);
143 /* 8'h00 */
144 pm_comm_write_byte(sid, FG_MEMIF_MEM_INTF_WR_DATA3, 0x00, 0);
145 pm_comm_read_byte(sid, FG_MEMIF_MEM_INTF_RD_DATA3, &value, 0);
146 /*perform iacs clear sequence 1'b0 */
147 pm_comm_read_byte(sid, FG_MEMIF_IMA_CFG, &value, 0);
148 value &= ~(IACS_CLR);
149 pm_comm_write_byte(sid, FG_MEMIF_IMA_CFG, value, 0);
150 }
151
152err:
153 pm_comm_write_byte(sid, FG_MEMIF_MEM_INTF_CFG, 0x00, 0);
154
155 return err;
156
157}