1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2008-2018 Fuzhou Rockchip Electronics Co., Ltd 4 */ 5 6 #include <common.h> 7 #include <i2c.h> 8 #include <errno.h> 9 #include <dm.h> 10 #include <dm/uclass.h> 11 #include <dm/uclass-id.h> 12 13 #include "rk618.h" 14 15 int rk618_i2c_write(struct rk618 *rk618, u16 reg, u32 val) 16 { 17 struct dm_i2c_chip *chip = dev_get_parent_platdata(rk618->dev); 18 struct i2c_msg msg; 19 u8 buf[] = { 20 (reg >> 0) & 0xff, (reg >> 8) & 0xff, 21 (val >> 0) & 0xff, (val >> 8) & 0xff, 22 (val >> 16) & 0xff, (val >> 24) & 0xff 23 }; 24 int ret; 25 26 msg.addr = chip->chip_addr; 27 msg.flags = 0; 28 msg.len = sizeof(buf); 29 msg.buf = buf; 30 31 ret = dm_i2c_xfer(rk618->dev, &msg, 1); 32 if (ret) { 33 dev_err(rk618->dev, "Could not execute transfer: %d\n", ret); 34 return ret; 35 } 36 37 return 0; 38 } 39 40 int rk618_i2c_read(struct rk618 *rk618, u16 reg, u32 *val) 41 { 42 struct dm_i2c_chip *chip = dev_get_parent_platdata(rk618->dev); 43 u32 data; 44 struct i2c_msg msg[] = { 45 { 46 .addr = chip->chip_addr, 47 .flags = 0, 48 .buf = (u8 *)®, 49 .len = 2, 50 }, { 51 .addr = chip->chip_addr, 52 .flags = I2C_M_RD, 53 .buf = (u8 *)&data, 54 .len = 4, 55 } 56 }; 57 int ret; 58 59 ret = dm_i2c_xfer(rk618->dev, msg, 2); 60 if (ret) { 61 dev_err(rk618->dev, "Could not execute transfer: %d\n", ret); 62 return ret; 63 } 64 65 *val = data; 66 67 return 0; 68 } 69 70 void rk618_frc_dither_disable(struct rk618 *rk618) 71 { 72 rk618_i2c_write(rk618, RK618_FRC_REG, FRC_DITHER_DISABLE); 73 } 74 75 void rk618_frc_dither_enable(struct rk618 *rk618) 76 { 77 rk618_i2c_write(rk618, RK618_FRC_REG, FRC_DITHER_ENABLE); 78 } 79 80 void rk618_frc_dclk_invert(struct rk618 *rk618) 81 { 82 rk618_i2c_write(rk618, RK618_FRC_REG, FRC_DCLK_INV); 83 } 84 85 static int rk618_power_on(struct rk618 *rk618) 86 { 87 if (rk618->power_supply) 88 regulator_set_enable(rk618->power_supply, 1); 89 90 if (dm_gpio_is_valid(&rk618->enable_gpio)) 91 dm_gpio_set_value(&rk618->enable_gpio, 1); 92 93 mdelay(2); 94 dm_gpio_set_value(&rk618->reset_gpio, 0); 95 mdelay(4); 96 dm_gpio_set_value(&rk618->reset_gpio, 1); 97 mdelay(50); 98 dm_gpio_set_value(&rk618->reset_gpio, 0); 99 100 return 0; 101 } 102 103 static void rk618_cru_init(struct rk618 *rk618) 104 { 105 rk618_i2c_write(rk618, 0x0058, 0xffff0000); 106 rk618_i2c_write(rk618, 0x005c, 0xffff191e); 107 rk618_i2c_write(rk618, 0x0060, 0x00000000); 108 rk618_i2c_write(rk618, 0x0064, 0xffff2186); 109 rk618_i2c_write(rk618, 0x0068, 0xffff1028); 110 rk618_i2c_write(rk618, 0x006c, 0xffff0641); 111 rk618_i2c_write(rk618, 0x0070, 0x00800000); 112 rk618_i2c_write(rk618, 0x0074, 0xffff1028); 113 rk618_i2c_write(rk618, 0x0078, 0xffff0641); 114 rk618_i2c_write(rk618, 0x007c, 0x00800000); 115 } 116 117 static int rk618_probe(struct udevice *dev) 118 { 119 struct rk618 *rk618 = dev_get_priv(dev); 120 int ret; 121 122 rk618->dev = dev; 123 124 ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, 125 "power-supply", 126 &rk618->power_supply); 127 if (ret && ret != -ENOENT) { 128 dev_err(dev, "Cannot get power supply: %d\n", ret); 129 return ret; 130 } 131 132 ret = gpio_request_by_name(dev, "enable-gpios", 0, 133 &rk618->enable_gpio, GPIOD_IS_OUT); 134 if (ret && ret != -ENOENT) { 135 dev_err(dev, "Cannot get enable GPIO: %d\n", ret); 136 return ret; 137 } 138 139 ret = gpio_request_by_name(dev, "reset-gpios", 0, 140 &rk618->reset_gpio, GPIOD_IS_OUT); 141 if (ret) { 142 dev_err(dev, "Cannot get reset GPIO: %d\n", ret); 143 return ret; 144 } 145 146 ret = clk_get_by_name(dev, "clkin", &rk618->clkin); 147 if (ret < 0) { 148 dev_err(dev, "failed to get clkin: %d\n", ret); 149 return ret; 150 } 151 152 ret = clk_set_rate(&rk618->clkin, 11289600); 153 if (ret < 0) { 154 dev_err(dev, "failed to set rate: %d\n", ret); 155 return ret; 156 } 157 158 clk_enable(&rk618->clkin); 159 160 ret = rk618_power_on(rk618); 161 if (ret) { 162 dev_err(dev, "failed to power on: %d\n", ret); 163 return ret; 164 } 165 166 rk618_cru_init(rk618); 167 168 return 0; 169 } 170 171 static const struct udevice_id rk618_of_match[] = { 172 { .compatible = "rockchip,rk618" }, 173 {} 174 }; 175 176 U_BOOT_DRIVER(rk618) = { 177 .name = "rk618", 178 .id = UCLASS_I2C_GENERIC, 179 .of_match = rk618_of_match, 180 .probe = rk618_probe, 181 .bind = dm_scan_fdt_dev, 182 .priv_auto_alloc_size = sizeof(struct rk618), 183 }; 184