^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * netup-init.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * NetUP Dual DVB-S2 CI driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2009 NetUP Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "cx23885.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "netup-init.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) static void i2c_av_write(struct i2c_adapter *i2c, u16 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) u8 buf[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct i2c_msg msg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) .addr = 0x88 >> 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) .buf = buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) .len = 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) buf[0] = reg >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) buf[1] = reg & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) buf[2] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) ret = i2c_transfer(i2c, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (ret != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) pr_err("%s: i2c write error!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static void i2c_av_write4(struct i2c_adapter *i2c, u16 reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) u8 buf[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct i2c_msg msg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .addr = 0x88 >> 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) .buf = buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .len = 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) buf[0] = reg >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) buf[1] = reg & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) buf[2] = val & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) buf[3] = (val >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) buf[4] = (val >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) buf[5] = val >> 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) ret = i2c_transfer(i2c, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (ret != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) pr_err("%s: i2c write error!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static u8 i2c_av_read(struct i2c_adapter *i2c, u16 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u8 buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct i2c_msg msg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) .addr = 0x88 >> 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .buf = buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) .len = 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) buf[0] = reg >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) buf[1] = reg & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) ret = i2c_transfer(i2c, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (ret != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) pr_err("%s: i2c write error!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) msg.flags = I2C_M_RD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) msg.len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) ret = i2c_transfer(i2c, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (ret != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) pr_err("%s: i2c read error!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static void i2c_av_and_or(struct i2c_adapter *i2c, u16 reg, unsigned and_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) u8 or_value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) i2c_av_write(i2c, reg, (i2c_av_read(i2c, reg) & and_mask) | or_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* set 27MHz on AUX_CLK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) void netup_initialize(struct cx23885_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct cx23885_i2c *i2c_bus = &dev->i2c_bus[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct i2c_adapter *i2c = &i2c_bus->i2c_adap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /* Stop microcontroller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) i2c_av_and_or(i2c, 0x803, ~0x10, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /* Aux PLL frac for 27 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) i2c_av_write4(i2c, 0x114, 0xea0eb3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* Aux PLL int for 27 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) i2c_av_write4(i2c, 0x110, 0x090319);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* start microcontroller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) i2c_av_and_or(i2c, 0x803, ~0x10, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }