Neil Armstrong | 3232585 | 2024-04-22 11:33:52 +0200 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* |
| 3 | * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. |
| 4 | * Copyright (c) 2024, Linaro Limited |
| 5 | * Author: Neil Armstrong <neil.armstrong@linaro.org> |
| 6 | * |
| 7 | * Based on Linux driver: drivers/i2c/busses/i2c-qcom-geni.c |
| 8 | */ |
| 9 | |
| 10 | #include <log.h> |
| 11 | #include <dm/device.h> |
| 12 | #include <dm/read.h> |
| 13 | #include <dm/device_compat.h> |
| 14 | #include <linux/delay.h> |
| 15 | #include <linux/errno.h> |
| 16 | #include <linux/err.h> |
| 17 | #include <linux/bitops.h> |
| 18 | #include <asm/io.h> |
| 19 | #include <i2c.h> |
| 20 | #include <fdtdec.h> |
| 21 | #include <clk.h> |
| 22 | #include <reset.h> |
| 23 | #include <time.h> |
| 24 | #include <soc/qcom/geni-se.h> |
| 25 | |
| 26 | #define SE_I2C_TX_TRANS_LEN 0x26c |
| 27 | #define SE_I2C_RX_TRANS_LEN 0x270 |
| 28 | #define SE_I2C_SCL_COUNTERS 0x278 |
| 29 | |
| 30 | #define SE_I2C_ERR (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN |\ |
| 31 | M_GP_IRQ_1_EN | M_GP_IRQ_3_EN | M_GP_IRQ_4_EN) |
| 32 | #define SE_I2C_ABORT BIT(1) |
| 33 | |
| 34 | /* M_CMD OP codes for I2C */ |
| 35 | #define I2C_WRITE 0x1 |
| 36 | #define I2C_READ 0x2 |
| 37 | #define I2C_WRITE_READ 0x3 |
| 38 | #define I2C_ADDR_ONLY 0x4 |
| 39 | #define I2C_BUS_CLEAR 0x6 |
| 40 | #define I2C_STOP_ON_BUS 0x7 |
| 41 | /* M_CMD params for I2C */ |
| 42 | #define PRE_CMD_DELAY BIT(0) |
| 43 | #define TIMESTAMP_BEFORE BIT(1) |
| 44 | #define STOP_STRETCH BIT(2) |
| 45 | #define TIMESTAMP_AFTER BIT(3) |
| 46 | #define POST_COMMAND_DELAY BIT(4) |
| 47 | #define IGNORE_ADD_NACK BIT(6) |
| 48 | #define READ_FINISHED_WITH_ACK BIT(7) |
| 49 | #define BYPASS_ADDR_PHASE BIT(8) |
| 50 | #define SLV_ADDR_MSK GENMASK(15, 9) |
| 51 | #define SLV_ADDR_SHFT 9 |
| 52 | /* I2C SCL COUNTER fields */ |
| 53 | #define HIGH_COUNTER_MSK GENMASK(29, 20) |
| 54 | #define HIGH_COUNTER_SHFT 20 |
| 55 | #define LOW_COUNTER_MSK GENMASK(19, 10) |
| 56 | #define LOW_COUNTER_SHFT 10 |
| 57 | #define CYCLE_COUNTER_MSK GENMASK(9, 0) |
| 58 | |
| 59 | #define I2C_PACK_TX BIT(0) |
| 60 | #define I2C_PACK_RX BIT(1) |
| 61 | |
| 62 | #define PACKING_BYTES_PW 4 |
| 63 | |
| 64 | #define GENI_I2C_IS_MASTER_HUB BIT(0) |
| 65 | |
| 66 | #define I2C_TIMEOUT_MS 100 |
| 67 | |
| 68 | struct geni_i2c_clk_fld { |
| 69 | u32 clk_freq_out; |
| 70 | u8 clk_div; |
| 71 | u8 t_high_cnt; |
| 72 | u8 t_low_cnt; |
| 73 | u8 t_cycle_cnt; |
| 74 | }; |
| 75 | |
| 76 | struct geni_i2c_priv { |
| 77 | fdt_addr_t wrapper; |
| 78 | phys_addr_t base; |
| 79 | struct clk core; |
| 80 | struct clk se; |
| 81 | u32 tx_wm; |
| 82 | bool is_master_hub; |
| 83 | const struct geni_i2c_clk_fld *clk_fld; |
| 84 | }; |
| 85 | |
| 86 | /* |
| 87 | * Hardware uses the underlying formula to calculate time periods of |
| 88 | * SCL clock cycle. Firmware uses some additional cycles excluded from the |
| 89 | * below formula and it is confirmed that the time periods are within |
| 90 | * specification limits. |
| 91 | * |
| 92 | * time of high period of SCL: t_high = (t_high_cnt * clk_div) / source_clock |
| 93 | * time of low period of SCL: t_low = (t_low_cnt * clk_div) / source_clock |
| 94 | * time of full period of SCL: t_cycle = (t_cycle_cnt * clk_div) / source_clock |
| 95 | * clk_freq_out = t / t_cycle |
| 96 | * source_clock = 19.2 MHz |
| 97 | */ |
| 98 | static const struct geni_i2c_clk_fld geni_i2c_clk_map[] = { |
| 99 | {I2C_SPEED_STANDARD_RATE, 7, 10, 11, 26}, |
| 100 | {I2C_SPEED_FAST_RATE, 2, 5, 12, 24}, |
| 101 | {I2C_SPEED_FAST_PLUS_RATE, 1, 3, 9, 18}, |
| 102 | }; |
| 103 | |
| 104 | static int geni_i2c_clk_map_idx(struct geni_i2c_priv *geni, unsigned int clk_freq) |
| 105 | { |
| 106 | const struct geni_i2c_clk_fld *itr = geni_i2c_clk_map; |
| 107 | int i; |
| 108 | |
| 109 | for (i = 0; i < ARRAY_SIZE(geni_i2c_clk_map); i++, itr++) { |
| 110 | if (itr->clk_freq_out == clk_freq) { |
| 111 | geni->clk_fld = itr; |
| 112 | return 0; |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | return -EINVAL; |
| 117 | } |
| 118 | |
| 119 | static void geni_i2c_setup_m_cmd(struct geni_i2c_priv *geni, u32 cmd, u32 params) |
| 120 | { |
| 121 | u32 m_cmd; |
| 122 | |
| 123 | m_cmd = (cmd << M_OPCODE_SHFT) | (params & M_PARAMS_MSK); |
| 124 | writel(m_cmd, geni->base + SE_GENI_M_CMD0); |
| 125 | } |
| 126 | |
| 127 | static void qcom_geni_i2c_conf(struct geni_i2c_priv *geni) |
| 128 | { |
| 129 | const struct geni_i2c_clk_fld *itr = geni->clk_fld; |
| 130 | u32 val; |
| 131 | |
| 132 | writel(0, geni->base + SE_GENI_CLK_SEL); |
| 133 | |
| 134 | val = (itr->clk_div << CLK_DIV_SHFT) | SER_CLK_EN; |
| 135 | writel(val, geni->base + GENI_SER_M_CLK_CFG); |
| 136 | |
| 137 | val = itr->t_high_cnt << HIGH_COUNTER_SHFT; |
| 138 | val |= itr->t_low_cnt << LOW_COUNTER_SHFT; |
| 139 | val |= itr->t_cycle_cnt; |
| 140 | writel(val, geni->base + SE_I2C_SCL_COUNTERS); |
| 141 | |
| 142 | writel(0xffffffff, geni->base + SE_GENI_M_IRQ_CLEAR); |
| 143 | } |
| 144 | |
| 145 | static int geni_i2c_fifo_tx_fill(struct geni_i2c_priv *geni, struct i2c_msg *msg) |
| 146 | { |
| 147 | ulong start = get_timer(0); |
| 148 | ulong cur_xfer = 0; |
| 149 | int i; |
| 150 | |
| 151 | while (get_timer(start) < I2C_TIMEOUT_MS) { |
| 152 | u32 status = readl(geni->base + SE_GENI_M_IRQ_STATUS); |
| 153 | |
| 154 | if (status & (M_CMD_ABORT_EN | |
| 155 | M_CMD_OVERRUN_EN | |
| 156 | M_ILLEGAL_CMD_EN | |
| 157 | M_CMD_FAILURE_EN | |
| 158 | M_GP_IRQ_1_EN | |
| 159 | M_GP_IRQ_3_EN | |
| 160 | M_GP_IRQ_4_EN)) { |
| 161 | writel(status, geni->base + SE_GENI_M_IRQ_CLEAR); |
| 162 | writel(0, geni->base + SE_GENI_TX_WATERMARK_REG); |
| 163 | return -EREMOTEIO; |
| 164 | } |
| 165 | |
| 166 | if ((status & M_TX_FIFO_WATERMARK_EN) == 0) { |
| 167 | udelay(1); |
| 168 | goto skip_fill; |
| 169 | } |
| 170 | |
| 171 | for (i = 0; i < geni->tx_wm; i++) { |
| 172 | u32 temp, tx = 0; |
| 173 | unsigned int p = 0; |
| 174 | |
| 175 | while (cur_xfer < msg->len && p < sizeof(tx)) { |
| 176 | temp = msg->buf[cur_xfer++]; |
| 177 | tx |= temp << (p * 8); |
| 178 | p++; |
| 179 | } |
| 180 | |
| 181 | writel(tx, geni->base + SE_GENI_TX_FIFOn); |
| 182 | |
| 183 | if (cur_xfer == msg->len) { |
| 184 | writel(0, geni->base + SE_GENI_TX_WATERMARK_REG); |
| 185 | break; |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | skip_fill: |
| 190 | writel(status, geni->base + SE_GENI_M_IRQ_CLEAR); |
| 191 | |
| 192 | if (status & M_CMD_DONE_EN) |
| 193 | return 0; |
| 194 | } |
| 195 | |
| 196 | return -ETIMEDOUT; |
| 197 | } |
| 198 | |
| 199 | static int geni_i2c_fifo_rx_drain(struct geni_i2c_priv *geni, struct i2c_msg *msg) |
| 200 | { |
| 201 | ulong start = get_timer(0); |
| 202 | ulong cur_xfer = 0; |
| 203 | int i; |
| 204 | |
| 205 | while (get_timer(start) < I2C_TIMEOUT_MS) { |
| 206 | u32 status = readl(geni->base + SE_GENI_M_IRQ_STATUS); |
| 207 | u32 rxstatus = readl(geni->base + SE_GENI_RX_FIFO_STATUS); |
| 208 | u32 rxcnt = rxstatus & RX_FIFO_WC_MSK; |
| 209 | |
| 210 | if (status & (M_CMD_ABORT_EN | |
| 211 | M_CMD_FAILURE_EN | |
| 212 | M_CMD_OVERRUN_EN | |
| 213 | M_ILLEGAL_CMD_EN | |
| 214 | M_GP_IRQ_1_EN | |
| 215 | M_GP_IRQ_3_EN | |
| 216 | M_GP_IRQ_4_EN)) { |
| 217 | writel(status, geni->base + SE_GENI_M_IRQ_CLEAR); |
| 218 | return -EREMOTEIO; |
| 219 | } |
| 220 | |
| 221 | if ((status & (M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN)) == 0) { |
| 222 | udelay(1); |
| 223 | goto skip_drain; |
| 224 | } |
| 225 | |
| 226 | for (i = 0; cur_xfer < msg->len && i < rxcnt; i++) { |
| 227 | u32 rx = readl(geni->base + SE_GENI_RX_FIFOn); |
| 228 | unsigned int p = 0; |
| 229 | |
| 230 | while (cur_xfer < msg->len && p < sizeof(rx)) { |
| 231 | msg->buf[cur_xfer++] = rx & 0xff; |
| 232 | rx >>= 8; |
| 233 | p++; |
| 234 | } |
| 235 | } |
| 236 | |
| 237 | skip_drain: |
| 238 | writel(status, geni->base + SE_GENI_M_IRQ_CLEAR); |
| 239 | |
| 240 | if (status & M_CMD_DONE_EN) |
| 241 | return 0; |
| 242 | } |
| 243 | |
| 244 | return -ETIMEDOUT; |
| 245 | } |
| 246 | |
| 247 | static int geni_i2c_xfer_tx(struct geni_i2c_priv *geni, struct i2c_msg *msg, u32 params) |
| 248 | { |
| 249 | writel(msg->len, geni->base + SE_I2C_TX_TRANS_LEN); |
| 250 | geni_i2c_setup_m_cmd(geni, I2C_WRITE, params); |
| 251 | writel(1, geni->base + SE_GENI_TX_WATERMARK_REG); |
| 252 | |
| 253 | return geni_i2c_fifo_tx_fill(geni, msg); |
| 254 | } |
| 255 | |
| 256 | static int geni_i2c_xfer_rx(struct geni_i2c_priv *geni, struct i2c_msg *msg, u32 params) |
| 257 | { |
| 258 | writel(msg->len, geni->base + SE_I2C_RX_TRANS_LEN); |
| 259 | geni_i2c_setup_m_cmd(geni, I2C_READ, params); |
| 260 | |
| 261 | return geni_i2c_fifo_rx_drain(geni, msg); |
| 262 | } |
| 263 | |
| 264 | static int geni_i2c_xfer(struct udevice *bus, struct i2c_msg msgs[], int num) |
| 265 | { |
| 266 | struct geni_i2c_priv *geni = dev_get_priv(bus); |
| 267 | int i, ret = 0; |
| 268 | |
| 269 | qcom_geni_i2c_conf(geni); |
| 270 | |
| 271 | for (i = 0; i < num; i++) { |
| 272 | struct i2c_msg *msg = &msgs[i]; |
| 273 | u32 m_param = i < (num - 1) ? STOP_STRETCH : 0; |
| 274 | |
| 275 | m_param |= ((msg->addr << SLV_ADDR_SHFT) & SLV_ADDR_MSK); |
| 276 | |
| 277 | if (msg->flags & I2C_M_RD) |
| 278 | ret = geni_i2c_xfer_rx(geni, msg, m_param); |
| 279 | else |
| 280 | ret = geni_i2c_xfer_tx(geni, msg, m_param); |
| 281 | |
| 282 | if (ret) |
| 283 | break; |
| 284 | } |
| 285 | |
| 286 | if (ret) { |
| 287 | if (ret == -ETIMEDOUT) { |
| 288 | u32 status; |
| 289 | |
| 290 | writel(M_GENI_CMD_ABORT, geni->base + SE_GENI_M_CMD_CTRL_REG); |
| 291 | |
| 292 | /* Wait until Abort has finished */ |
| 293 | do { |
| 294 | status = readl(geni->base + SE_GENI_M_IRQ_STATUS); |
| 295 | } while ((status & M_CMD_ABORT_EN) == 0); |
| 296 | |
| 297 | writel(status, geni->base + SE_GENI_M_IRQ_STATUS); |
| 298 | } |
| 299 | |
| 300 | return ret; |
| 301 | } |
| 302 | |
| 303 | return 0; |
| 304 | } |
| 305 | |
| 306 | static int geni_i2c_enable_clocks(struct udevice *dev, struct geni_i2c_priv *geni) |
| 307 | { |
| 308 | int ret; |
| 309 | |
| 310 | if (geni->is_master_hub) { |
| 311 | ret = clk_enable(&geni->core); |
| 312 | if (ret) { |
| 313 | dev_err(dev, "clk_enable core failed %d\n", ret); |
| 314 | return ret; |
| 315 | } |
| 316 | } |
| 317 | |
| 318 | ret = clk_enable(&geni->se); |
| 319 | if (ret) { |
| 320 | dev_err(dev, "clk_enable se failed %d\n", ret); |
| 321 | return ret; |
| 322 | } |
| 323 | |
| 324 | return 0; |
| 325 | } |
| 326 | |
| 327 | static int geni_i2c_disable_clocks(struct udevice *dev, struct geni_i2c_priv *geni) |
| 328 | { |
| 329 | int ret; |
| 330 | |
| 331 | if (geni->is_master_hub) { |
| 332 | ret = clk_disable(&geni->core); |
| 333 | if (ret) { |
| 334 | dev_err(dev, "clk_enable core failed %d\n", ret); |
| 335 | return ret; |
| 336 | } |
| 337 | } |
| 338 | |
| 339 | ret = clk_disable(&geni->se); |
| 340 | if (ret) { |
| 341 | dev_err(dev, "clk_enable se failed %d\n", ret); |
| 342 | return ret; |
| 343 | } |
| 344 | |
| 345 | return 0; |
| 346 | } |
| 347 | |
| 348 | #define NUM_PACKING_VECTORS 4 |
| 349 | #define PACKING_START_SHIFT 5 |
| 350 | #define PACKING_DIR_SHIFT 4 |
| 351 | #define PACKING_LEN_SHIFT 1 |
| 352 | #define PACKING_STOP_BIT BIT(0) |
| 353 | #define PACKING_VECTOR_SHIFT 10 |
| 354 | static void geni_i2c_config_packing(struct geni_i2c_priv *geni, int bpw, |
| 355 | int pack_words, bool msb_to_lsb, |
| 356 | bool tx_cfg, bool rx_cfg) |
| 357 | { |
| 358 | u32 cfg0, cfg1, cfg[NUM_PACKING_VECTORS] = {0}; |
| 359 | int len; |
| 360 | int temp_bpw = bpw; |
| 361 | int idx_start = msb_to_lsb ? bpw - 1 : 0; |
| 362 | int idx = idx_start; |
| 363 | int idx_delta = msb_to_lsb ? -BITS_PER_BYTE : BITS_PER_BYTE; |
| 364 | int ceil_bpw = ALIGN(bpw, BITS_PER_BYTE); |
| 365 | int iter = (ceil_bpw * pack_words) / BITS_PER_BYTE; |
| 366 | int i; |
| 367 | |
| 368 | if (iter <= 0 || iter > NUM_PACKING_VECTORS) |
| 369 | return; |
| 370 | |
| 371 | for (i = 0; i < iter; i++) { |
| 372 | len = min_t(int, temp_bpw, BITS_PER_BYTE) - 1; |
| 373 | cfg[i] = idx << PACKING_START_SHIFT; |
| 374 | cfg[i] |= msb_to_lsb << PACKING_DIR_SHIFT; |
| 375 | cfg[i] |= len << PACKING_LEN_SHIFT; |
| 376 | |
| 377 | if (temp_bpw <= BITS_PER_BYTE) { |
| 378 | idx = ((i + 1) * BITS_PER_BYTE) + idx_start; |
| 379 | temp_bpw = bpw; |
| 380 | } else { |
| 381 | idx = idx + idx_delta; |
| 382 | temp_bpw = temp_bpw - BITS_PER_BYTE; |
| 383 | } |
| 384 | } |
| 385 | cfg[iter - 1] |= PACKING_STOP_BIT; |
| 386 | cfg0 = cfg[0] | (cfg[1] << PACKING_VECTOR_SHIFT); |
| 387 | cfg1 = cfg[2] | (cfg[3] << PACKING_VECTOR_SHIFT); |
| 388 | |
| 389 | if (tx_cfg) { |
| 390 | writel(cfg0, geni->base + SE_GENI_TX_PACKING_CFG0); |
| 391 | writel(cfg1, geni->base + SE_GENI_TX_PACKING_CFG1); |
| 392 | } |
| 393 | if (rx_cfg) { |
| 394 | writel(cfg0, geni->base + SE_GENI_RX_PACKING_CFG0); |
| 395 | writel(cfg1, geni->base + SE_GENI_RX_PACKING_CFG1); |
| 396 | } |
| 397 | |
| 398 | /* |
| 399 | * Number of protocol words in each FIFO entry |
| 400 | * 0 - 4x8, four words in each entry, max word size of 8 bits |
| 401 | * 1 - 2x16, two words in each entry, max word size of 16 bits |
| 402 | * 2 - 1x32, one word in each entry, max word size of 32 bits |
| 403 | * 3 - undefined |
| 404 | */ |
| 405 | if (pack_words || bpw == 32) |
| 406 | writel(bpw / 16, geni->base + SE_GENI_BYTE_GRAN); |
| 407 | } |
| 408 | |
| 409 | static void geni_i2c_init(struct geni_i2c_priv *geni, unsigned int tx_depth) |
| 410 | { |
| 411 | u32 val; |
| 412 | |
| 413 | writel(0, geni->base + SE_GSI_EVENT_EN); |
| 414 | writel(0xffffffff, geni->base + SE_GENI_M_IRQ_CLEAR); |
| 415 | writel(0xffffffff, geni->base + SE_GENI_S_IRQ_CLEAR); |
| 416 | writel(0xffffffff, geni->base + SE_IRQ_EN); |
| 417 | |
| 418 | val = readl(geni->base + GENI_CGC_CTRL); |
| 419 | val |= DEFAULT_CGC_EN; |
| 420 | writel(val, geni->base + GENI_CGC_CTRL); |
| 421 | |
| 422 | writel(DEFAULT_IO_OUTPUT_CTRL_MSK, geni->base + GENI_OUTPUT_CTRL); |
| 423 | writel(FORCE_DEFAULT, geni->base + GENI_FORCE_DEFAULT_REG); |
| 424 | |
| 425 | val = readl(geni->base + SE_IRQ_EN); |
| 426 | val |= GENI_M_IRQ_EN | GENI_S_IRQ_EN; |
| 427 | writel(val, geni->base + SE_IRQ_EN); |
| 428 | |
| 429 | val = readl(geni->base + SE_GENI_DMA_MODE_EN); |
| 430 | val &= ~GENI_DMA_MODE_EN; |
| 431 | writel(val, geni->base + SE_GENI_DMA_MODE_EN); |
| 432 | |
| 433 | writel(0, geni->base + SE_GSI_EVENT_EN); |
| 434 | |
| 435 | writel(tx_depth - 1, geni->base + SE_GENI_RX_WATERMARK_REG); |
| 436 | writel(tx_depth, geni->base + SE_GENI_RX_RFR_WATERMARK_REG); |
| 437 | |
| 438 | val = readl(geni->base + SE_GENI_M_IRQ_EN); |
| 439 | val |= M_COMMON_GENI_M_IRQ_EN; |
| 440 | val |= M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN; |
| 441 | val |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN; |
| 442 | writel(val, geni->base + SE_GENI_M_IRQ_EN); |
| 443 | |
| 444 | val = readl(geni->base + SE_GENI_S_IRQ_EN); |
| 445 | val |= S_COMMON_GENI_S_IRQ_EN; |
| 446 | writel(val, geni->base + SE_GENI_S_IRQ_EN); |
| 447 | } |
| 448 | |
| 449 | static u32 geni_i2c_get_tx_fifo_depth(struct geni_i2c_priv *geni) |
| 450 | { |
| 451 | u32 val, hw_version, hw_major, hw_minor, tx_fifo_depth_mask; |
| 452 | |
| 453 | hw_version = readl(geni->wrapper + QUP_HW_VER_REG); |
| 454 | hw_major = GENI_SE_VERSION_MAJOR(hw_version); |
| 455 | hw_minor = GENI_SE_VERSION_MINOR(hw_version); |
| 456 | |
| 457 | if ((hw_major == 3 && hw_minor >= 10) || hw_major > 3) |
| 458 | tx_fifo_depth_mask = TX_FIFO_DEPTH_MSK_256_BYTES; |
| 459 | else |
| 460 | tx_fifo_depth_mask = TX_FIFO_DEPTH_MSK; |
| 461 | |
| 462 | val = readl(geni->base + SE_HW_PARAM_0); |
| 463 | |
| 464 | return (val & tx_fifo_depth_mask) >> TX_FIFO_DEPTH_SHFT; |
| 465 | } |
| 466 | |
| 467 | static int geni_i2c_probe(struct udevice *dev) |
| 468 | { |
| 469 | ofnode parent_node = ofnode_get_parent(dev_ofnode(dev)); |
| 470 | struct geni_i2c_priv *geni = dev_get_priv(dev); |
| 471 | u32 proto, tx_depth, fifo_disable; |
| 472 | int ret; |
| 473 | |
| 474 | geni->is_master_hub = dev_get_driver_data(dev) & GENI_I2C_IS_MASTER_HUB; |
| 475 | |
| 476 | geni->wrapper = ofnode_get_addr(parent_node); |
| 477 | if (geni->wrapper == FDT_ADDR_T_NONE) |
| 478 | return -EINVAL; |
| 479 | |
| 480 | geni->base = (phys_addr_t)dev_read_addr_ptr(dev); |
| 481 | if (!geni->base) |
| 482 | return -EINVAL; |
| 483 | |
| 484 | if (geni->is_master_hub) { |
| 485 | ret = clk_get_by_name(dev, "core", &geni->core); |
| 486 | if (ret) { |
| 487 | dev_err(dev, "clk_get_by_name(core) failed: %d\n", ret); |
| 488 | return ret; |
| 489 | } |
| 490 | } |
| 491 | |
| 492 | ret = clk_get_by_name(dev, "se", &geni->se); |
| 493 | if (ret) { |
| 494 | dev_err(dev, "clk_get_by_name(se) failed: %d\n", ret); |
| 495 | return ret; |
| 496 | } |
| 497 | |
| 498 | geni_i2c_enable_clocks(dev, geni); |
| 499 | |
| 500 | proto = readl(geni->base + GENI_FW_REVISION_RO); |
| 501 | proto &= FW_REV_PROTOCOL_MSK; |
| 502 | proto >>= FW_REV_PROTOCOL_SHFT; |
| 503 | |
| 504 | if (proto != GENI_SE_I2C) { |
| 505 | dev_err(dev, "Invalid proto %d\n", proto); |
| 506 | geni_i2c_disable_clocks(dev, geni); |
| 507 | return -ENXIO; |
| 508 | } |
| 509 | |
| 510 | fifo_disable = readl(geni->base + GENI_IF_DISABLE_RO) & FIFO_IF_DISABLE; |
| 511 | if (fifo_disable) { |
| 512 | geni_i2c_disable_clocks(dev, geni); |
| 513 | dev_err(dev, "FIFO mode disabled, DMA mode unsupported\n"); |
| 514 | return -ENXIO; |
| 515 | } |
| 516 | |
| 517 | if (!geni->is_master_hub) { |
| 518 | tx_depth = geni_i2c_get_tx_fifo_depth(geni); |
| 519 | if (!tx_depth) { |
| 520 | geni_i2c_disable_clocks(dev, geni); |
| 521 | dev_err(dev, "Invalid TX FIFO depth\n"); |
| 522 | return -ENXIO; |
| 523 | } |
| 524 | } else { |
| 525 | tx_depth = 16; |
| 526 | } |
| 527 | geni->tx_wm = tx_depth - 1; |
| 528 | |
| 529 | geni_i2c_init(geni, tx_depth); |
| 530 | geni_i2c_config_packing(geni, BITS_PER_BYTE, |
| 531 | PACKING_BYTES_PW, true, true, true); |
| 532 | |
| 533 | /* Setup for standard rate */ |
| 534 | return geni_i2c_clk_map_idx(geni, I2C_SPEED_STANDARD_RATE); |
| 535 | } |
| 536 | |
| 537 | static int geni_i2c_set_bus_speed(struct udevice *dev, unsigned int clk_freq) |
| 538 | { |
| 539 | struct geni_i2c_priv *geni = dev_get_priv(dev); |
| 540 | |
| 541 | return geni_i2c_clk_map_idx(geni, clk_freq); |
| 542 | } |
| 543 | |
| 544 | static const struct dm_i2c_ops geni_i2c_ops = { |
| 545 | .xfer = geni_i2c_xfer, |
| 546 | .set_bus_speed = geni_i2c_set_bus_speed, |
| 547 | }; |
| 548 | |
| 549 | static const struct udevice_id geni_i2c_ids[] = { |
| 550 | { .compatible = "qcom,geni-i2c" }, |
| 551 | { .compatible = "qcom,geni-i2c-master-hub", .data = GENI_I2C_IS_MASTER_HUB}, |
| 552 | {} |
| 553 | }; |
| 554 | |
| 555 | U_BOOT_DRIVER(i2c_geni) = { |
| 556 | .name = "i2c_geni", |
| 557 | .id = UCLASS_I2C, |
| 558 | .of_match = geni_i2c_ids, |
| 559 | .probe = geni_i2c_probe, |
| 560 | .priv_auto = sizeof(struct geni_i2c_priv), |
| 561 | .ops = &geni_i2c_ops, |
| 562 | }; |
| 563 | |
| 564 | static const struct udevice_id geni_i2c_master_hub_ids[] = { |
| 565 | { .compatible = "qcom,geni-se-i2c-master-hub" }, |
| 566 | { } |
| 567 | }; |
| 568 | |
| 569 | U_BOOT_DRIVER(geni_i2c_master_hub) = { |
| 570 | .name = "geni-se-master-hub", |
| 571 | .id = UCLASS_NOP, |
| 572 | .of_match = geni_i2c_master_hub_ids, |
| 573 | .bind = dm_scan_fdt_dev, |
| 574 | .flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF, |
| 575 | }; |