Tom Rini | 10e4779 | 2018-05-06 17:58:06 -0400 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0+ |
Shaveta Leekha | afe5b06 | 2014-04-11 14:12:39 +0530 | [diff] [blame] | 2 | /* |
| 3 | * Copyright 2013 Freescale Semiconductor, Inc. |
Shaveta Leekha | afe5b06 | 2014-04-11 14:12:39 +0530 | [diff] [blame] | 4 | */ |
| 5 | |
| 6 | /* Power-One ZM7300 DPM */ |
| 7 | #include "zm7300.h" |
| 8 | |
| 9 | #define DPM_WP 0x96 |
| 10 | #define WRP_OPCODE 0x01 |
| 11 | #define WRM_OPCODE 0x02 |
| 12 | #define RRP_OPCODE 0x11 |
| 13 | |
| 14 | #define DPM_SUCCESS 0x01 |
| 15 | #define DPM_EXEC_FAIL 0x00 |
| 16 | |
| 17 | static const uint16_t hex_to_1_10mv[] = { |
| 18 | 5000, |
| 19 | 5125, |
| 20 | 5250, |
| 21 | 5375, |
| 22 | 5500, |
| 23 | 5625, |
| 24 | 5750, |
| 25 | 5875, |
| 26 | 6000, |
| 27 | 6125, |
| 28 | 6250, |
| 29 | 6375, |
| 30 | 6500, |
| 31 | 6625, |
| 32 | 6750, |
| 33 | 6875, |
| 34 | 7000, |
| 35 | 7125, |
| 36 | 7250, |
| 37 | 7375, |
| 38 | 7500, |
| 39 | 7625, |
| 40 | 7750, |
| 41 | 7875, |
| 42 | 8000, |
| 43 | 8125, |
| 44 | 8250, |
| 45 | 8375, |
| 46 | 8500, |
| 47 | 8625, |
| 48 | 8750, |
| 49 | 8875, |
| 50 | 9000, |
| 51 | 9125, |
| 52 | 9250, |
| 53 | 9375, |
| 54 | 9500, /* 0.95mV */ |
| 55 | 9625, |
| 56 | 9750, |
| 57 | 9875, |
| 58 | 10000, /* 1.0V */ |
| 59 | 10125, |
| 60 | 10250, |
| 61 | 10375, |
| 62 | 10500, |
| 63 | 10625, |
| 64 | 10750, |
| 65 | 10875, |
| 66 | 11000, |
| 67 | 11125, |
| 68 | 11250, |
| 69 | 11375, |
| 70 | 11500, |
| 71 | 11625, |
| 72 | 11750, |
| 73 | 11875, |
| 74 | 12000, |
| 75 | 12125, |
| 76 | 12250, |
| 77 | 12375, |
| 78 | 0, /* reserved */ |
| 79 | }; |
| 80 | |
| 81 | |
| 82 | /* Read Data d from Register r of POL p */ |
| 83 | u8 dpm_rrp(uchar r) |
| 84 | { |
| 85 | u8 ret[5]; |
| 86 | |
| 87 | ret[0] = RRP_OPCODE; |
| 88 | /* POL is 0 */ |
| 89 | ret[1] = 0; |
| 90 | ret[2] = r; |
| 91 | i2c_read(I2C_DPM_ADDR, 0, -3, ret, 2); |
| 92 | if (ret[1] == DPM_SUCCESS) { /* the DPM returned success as status */ |
| 93 | debug("RRP_OPCODE returned success data is %x\n", ret[0]); |
| 94 | return ret[0]; |
| 95 | } else { |
| 96 | return -1; |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | /* Write Data d into DPM register r (RAM) */ |
| 101 | int dpm_wrm(u8 r, u8 d) |
| 102 | { |
| 103 | u8 ret[5]; |
| 104 | |
| 105 | ret[0] = WRM_OPCODE; |
| 106 | ret[1] = r; |
| 107 | ret[2] = d; |
| 108 | i2c_read(I2C_DPM_ADDR, 0, -3, ret, 1); |
| 109 | if (ret[0] == DPM_SUCCESS) { /* the DPM returned success as status */ |
| 110 | debug("WRM_OPCODE returned success data is %x\n", ret[0]); |
| 111 | return ret[0]; |
| 112 | } else { |
| 113 | return -1; |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | /* Write Data d into Register r of POL(s) a */ |
| 118 | int dpm_wrp(u8 r, u8 d) |
| 119 | { |
| 120 | u8 ret[7]; |
| 121 | |
| 122 | ret[0] = WRP_OPCODE; |
| 123 | /* only POL0 is present */ |
| 124 | ret[1] = 0x01; |
| 125 | ret[2] = 0x00; |
| 126 | ret[3] = 0x00; |
| 127 | ret[4] = 0x00; |
| 128 | ret[5] = r; |
| 129 | ret[6] = d; |
| 130 | i2c_read(I2C_DPM_ADDR, 0, -7, ret, 1); |
| 131 | if (ret[0] == DPM_SUCCESS) { /* the DPM returned success as status */ |
| 132 | debug("WRP_OPCODE returned success data is %x\n", ret[0]); |
| 133 | return 0; |
| 134 | } else { |
| 135 | return -1; |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | /* Uses the DPM command RRP */ |
| 140 | u8 zm_read(uchar reg) |
| 141 | { |
Masahiro Yamada | 04cfea5 | 2016-09-06 22:17:38 +0900 | [diff] [blame] | 142 | return dpm_rrp(reg); |
Shaveta Leekha | afe5b06 | 2014-04-11 14:12:39 +0530 | [diff] [blame] | 143 | } |
| 144 | |
| 145 | /* ZM_write -- |
| 146 | Steps: |
| 147 | a. Write data to the register |
| 148 | b. Read data from register and compare to written value |
| 149 | c. Return return_code & voltage_read |
| 150 | */ |
| 151 | u8 zm_write(u8 reg, u8 data) |
| 152 | { |
| 153 | u8 d; |
| 154 | |
| 155 | /* write data to register */ |
| 156 | dpm_wrp(reg, data); |
| 157 | |
| 158 | /* read register and compare to written value */ |
| 159 | d = dpm_rrp(reg); |
| 160 | if (d != data) { |
| 161 | printf("zm_write : Comparison register data failed\n"); |
| 162 | return -1; |
| 163 | } |
| 164 | |
| 165 | return d; |
| 166 | } |
| 167 | |
| 168 | /* zm_write_out_voltage |
| 169 | * voltage in 1/10 mV |
| 170 | */ |
| 171 | int zm_write_voltage(int voltage) |
| 172 | { |
| 173 | u8 reg = 0x7, vid; |
| 174 | uint16_t voltage_read; |
| 175 | u8 ret; |
| 176 | |
| 177 | vid = (voltage - 5000) / ZM_STEP; |
| 178 | |
| 179 | ret = zm_write(reg, vid); |
| 180 | if (ret != -1) { |
| 181 | voltage_read = hex_to_1_10mv[ret]; |
| 182 | debug("voltage set to %dmV\n", voltage_read/10); |
| 183 | return voltage_read; |
| 184 | } |
| 185 | return -1; |
| 186 | } |
| 187 | |
| 188 | /* zm_read_out_voltage |
| 189 | * voltage in 1/10 mV |
| 190 | */ |
| 191 | int zm_read_voltage(void) |
| 192 | { |
| 193 | u8 reg = 0x7; |
| 194 | u8 ret; |
| 195 | int voltage; |
| 196 | |
| 197 | ret = zm_read(reg); |
| 198 | if (ret != -1) { |
| 199 | voltage = hex_to_1_10mv[ret]; |
| 200 | debug("Voltage read is %dmV\n", voltage/10); |
| 201 | return voltage; |
| 202 | } else { |
| 203 | return -1; |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | int zm_disable_wp() |
| 208 | { |
| 209 | u8 new_wp_value; |
| 210 | |
| 211 | /* Disable using Write-Protect register 0x96 */ |
| 212 | new_wp_value = 0x8; |
| 213 | if ((dpm_wrm(DPM_WP, new_wp_value)) < 0) { |
| 214 | printf("Disable Write-Protect register failed\n"); |
| 215 | return -1; |
| 216 | } |
| 217 | return 0; |
| 218 | } |
| 219 | |
| 220 | int zm_enable_wp() |
| 221 | { |
| 222 | u8 orig_wp_value; |
| 223 | orig_wp_value = 0x0; |
| 224 | |
| 225 | /* Enable using Write-Protect register 0x96 */ |
| 226 | if ((dpm_wrm(DPM_WP, orig_wp_value)) < 0) { |
| 227 | printf("Enable Write-Protect register failed\n"); |
| 228 | return -1; |
| 229 | } |
| 230 | return 0; |
| 231 | } |
| 232 | |