summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/atsha204a-i2c.c90
-rw-r--r--drivers/misc/rockchip-io-domain.c79
2 files changed, 136 insertions, 33 deletions
diff --git a/drivers/misc/atsha204a-i2c.c b/drivers/misc/atsha204a-i2c.c
index d3c515828ff..707daa90bdb 100644
--- a/drivers/misc/atsha204a-i2c.c
+++ b/drivers/misc/atsha204a-i2c.c
@@ -21,7 +21,6 @@
#include <linux/bitrev.h>
#include <u-boot/crc.h>
-#define ATSHA204A_TWLO_US 60
#define ATSHA204A_TWHI_US 2500
#define ATSHA204A_TRANSACTION_TIMEOUT 100000
#define ATSHA204A_TRANSACTION_RETRY 5
@@ -34,6 +33,48 @@ static inline u16 atsha204a_crc16(const u8 *buffer, size_t len)
return bitrev16(crc16(0, buffer, len));
}
+static int atsha204a_ping_bus(struct udevice *dev)
+{
+ struct udevice *bus = dev_get_parent(dev);
+ struct i2c_msg msg;
+ int speed;
+ int res;
+ u8 val = 0;
+
+ speed = dm_i2c_get_bus_speed(bus);
+ if (speed != I2C_SPEED_STANDARD_RATE) {
+ int rv;
+
+ rv = dm_i2c_set_bus_speed(bus, I2C_SPEED_STANDARD_RATE);
+ if (rv)
+ debug("Couldn't change the I2C bus speed\n");
+ }
+
+ /*
+ * The I2C drivers don't support sending messages when NAK is received.
+ * This chip requires wake up low signal on SDA for >= 60us.
+ * To achieve this, we slow the bus to 100kHz and send an empty
+ * message to address 0. This will hold the SDA line low for the
+ * required time to wake up the chip.
+ */
+ msg.addr = 0;
+ msg.flags = I2C_M_STOP;
+ msg.len = sizeof(val);
+ msg.buf = &val;
+
+ res = dm_i2c_xfer(dev, &msg, 1);
+
+ if (speed != I2C_SPEED_STANDARD_RATE) {
+ int rv;
+
+ rv = dm_i2c_set_bus_speed(bus, speed);
+ if (rv)
+ debug("Couldn't restore the I2C bus speed\n");
+ }
+
+ return res;
+}
+
static int atsha204a_send(struct udevice *dev, const u8 *buf, u8 len)
{
fdt_addr_t *priv = dev_get_priv(dev);
@@ -94,42 +135,33 @@ static int atsha204a_recv_resp(struct udevice *dev,
int atsha204a_wakeup(struct udevice *dev)
{
- u8 req[4];
struct atsha204a_resp resp;
- int try, res;
+ int res;
debug("Waking up ATSHA204A\n");
- for (try = 1; try <= 10; ++try) {
- debug("Try %i... ", try);
+ /*
+ * The device ignores any levels or transitions on the SCL pin
+ * when the device is idle, asleep or during waking up.
+ * Don't check for error when waking up the device.
+ */
+ atsha204a_ping_bus(dev);
- /*
- * The device ignores any levels or transitions on the SCL pin
- * when the device is idle, asleep or during waking up.
- * Don't check for error when waking up the device.
- */
- memset(req, 0, 4);
- atsha204a_send(dev, req, 4);
-
- udelay(ATSHA204A_TWLO_US + ATSHA204A_TWHI_US);
-
- res = atsha204a_recv_resp(dev, &resp);
- if (res) {
- debug("failed on receiving response, ending\n");
- return res;
- }
+ udelay(ATSHA204A_TWHI_US);
- if (resp.code != ATSHA204A_STATUS_AFTER_WAKE) {
- debug ("failed (responce code = %02x), ending\n",
- resp.code);
- return -EBADMSG;
- }
+ res = atsha204a_recv_resp(dev, &resp);
+ if (res) {
+ debug("failed on receiving response, ending\n");
+ return res;
+ }
- debug("success\n");
- return 0;
+ if (resp.code != ATSHA204A_STATUS_AFTER_WAKE) {
+ debug("failed (response code = %02x), ending\n", resp.code);
+ return -EBADMSG;
}
- return -ETIMEDOUT;
+ debug("success\n");
+ return 0;
}
int atsha204a_idle(struct udevice *dev)
@@ -146,7 +178,7 @@ int atsha204a_idle(struct udevice *dev)
int atsha204a_sleep(struct udevice *dev)
{
int res;
- u8 req = ATSHA204A_FUNC_IDLE;
+ u8 req = ATSHA204A_FUNC_SLEEP;
res = atsha204a_send(dev, &req, 1);
if (res)
diff --git a/drivers/misc/rockchip-io-domain.c b/drivers/misc/rockchip-io-domain.c
index 3f6227f993f..0ffea32ef07 100644
--- a/drivers/misc/rockchip-io-domain.c
+++ b/drivers/misc/rockchip-io-domain.c
@@ -5,7 +5,6 @@
* Ported from linux drivers/soc/rockchip/io-domain.c
*/
-#include <common.h>
#include <dm.h>
#include <dm/device_compat.h>
#include <regmap.h>
@@ -28,6 +27,10 @@
#define MAX_VOLTAGE_1_8 1980000
#define MAX_VOLTAGE_3_3 3600000
+#define RK3399_PMUGRF_CON0 0x180
+#define RK3399_PMUGRF_CON0_VSEL BIT(8)
+#define RK3399_PMUGRF_VSEL_SUPPLY_NUM 9
+
#define RK3568_PMU_GRF_IO_VSEL0 0x0140
#define RK3568_PMU_GRF_IO_VSEL1 0x0144
#define RK3568_PMU_GRF_IO_VSEL2 0x0148
@@ -35,10 +38,10 @@
struct rockchip_iodomain_soc_data {
int grf_offset;
const char *supply_names[MAX_SUPPLIES];
- int (*write)(struct regmap *grf, int idx, int uV);
+ int (*write)(struct regmap *grf, uint offset, int idx, int uV);
};
-static int rk3568_iodomain_write(struct regmap *grf, int idx, int uV)
+static int rk3568_iodomain_write(struct regmap *grf, uint offset, int idx, int uV)
{
u32 is_3v3 = uV > MAX_VOLTAGE_1_8;
u32 val0, val1;
@@ -78,6 +81,64 @@ static int rk3568_iodomain_write(struct regmap *grf, int idx, int uV)
return 0;
}
+static int rockchip_iodomain_write(struct regmap *grf, uint offset, int idx, int uV)
+{
+ u32 val;
+
+ /* set value bit */
+ val = (uV > MAX_VOLTAGE_1_8) ? 0 : 1;
+ val <<= idx;
+
+ /* apply hiword-mask */
+ val |= (BIT(idx) << 16);
+
+ return regmap_write(grf, offset, val);
+}
+
+static int rk3399_pmu_iodomain_write(struct regmap *grf, uint offset, int idx, int uV)
+{
+ int ret = rockchip_iodomain_write(grf, offset, idx, uV);
+
+ if (!ret && idx == RK3399_PMUGRF_VSEL_SUPPLY_NUM) {
+ /*
+ * set pmu io iodomain to also use this framework
+ * instead of a special gpio.
+ */
+ u32 val = RK3399_PMUGRF_CON0_VSEL | (RK3399_PMUGRF_CON0_VSEL << 16);
+ ret = regmap_write(grf, RK3399_PMUGRF_CON0, val);
+ }
+
+ return ret;
+}
+
+static const struct rockchip_iodomain_soc_data soc_data_rk3399 = {
+ .grf_offset = 0xe640,
+ .supply_names = {
+ "bt656-supply", /* APIO2_VDD */
+ "audio-supply", /* APIO5_VDD */
+ "sdmmc-supply", /* SDMMC0_VDD */
+ "gpio1830-supply", /* APIO4_VDD */
+ },
+ .write = rockchip_iodomain_write,
+};
+
+static const struct rockchip_iodomain_soc_data soc_data_rk3399_pmu = {
+ .grf_offset = 0x180,
+ .supply_names = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "pmu1830-supply", /* PMUIO2_VDD */
+ },
+ .write = rk3399_pmu_iodomain_write,
+};
+
static const struct rockchip_iodomain_soc_data soc_data_rk3568_pmu = {
.grf_offset = 0x140,
.supply_names = {
@@ -96,6 +157,14 @@ static const struct rockchip_iodomain_soc_data soc_data_rk3568_pmu = {
static const struct udevice_id rockchip_iodomain_ids[] = {
{
+ .compatible = "rockchip,rk3399-io-voltage-domain",
+ .data = (ulong)&soc_data_rk3399,
+ },
+ {
+ .compatible = "rockchip,rk3399-pmu-io-voltage-domain",
+ .data = (ulong)&soc_data_rk3399_pmu,
+ },
+ {
.compatible = "rockchip,rk3568-pmu-io-voltage-domain",
.data = (ulong)&soc_data_rk3568_pmu,
},
@@ -152,7 +221,9 @@ static int rockchip_iodomain_probe(struct udevice *dev)
continue;
}
- soc_data->write(grf, i, uV);
+ ret = soc_data->write(grf, soc_data->grf_offset, i, uV);
+ if (ret)
+ dev_err(dev, "%s: Couldn't write to GRF\n", supply_name);
}
return 0;