diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 05a177744a47..69e9e1e03a06 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1006,6 +1006,17 @@ config MFD_RK618 help if you say yes here you get support for the RK618 from Rockchip. +config MFD_RK628 + tristate "Rockchip RK628 MFD Driver" + depends on I2C + depends on OF + select MFD_CORE + select REGMAP_I2C + select REGMAP_IRQ + select PINCTRL_RK628 + help + if you say yes here you get support for the RK628 from Rockchip. + config MFD_RK808 tristate "Rockchip RK805/RK808/RK809/RK816/RK817/RK818 Power Management Chip" depends on I2C && OF diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index fab3e101331c..7c0e7b365502 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -207,6 +207,7 @@ obj-$(CONFIG_MFD_PALMAS) += palmas.o obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o obj-$(CONFIG_MFD_RK618) += rk618.o +obj-$(CONFIG_MFD_RK628) += rk628.o obj-$(CONFIG_MFD_RK808) += rk808.o obj-$(CONFIG_MFD_RK1000) += rk1000-core.o obj-$(CONFIG_MFD_RN5T618) += rn5t618.o diff --git a/drivers/mfd/rk628.c b/drivers/mfd/rk628.c new file mode 100644 index 000000000000..998941d80c4d --- /dev/null +++ b/drivers/mfd/rk628.c @@ -0,0 +1,471 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Rockchip Electronics Co. Ltd. + * + * Author: Wyon Bi + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + RK628_IRQ_HDMITX_HPD_HIGH, + RK628_IRQ_HDMITX_HPD_LOW, + RK628_IRQ_HDMITX, + RK628_IRQ_GVI, + RK628_IRQ_DSI1, + RK628_IRQ_DSI0, + RK628_IRQ_CSI, + RK628_IRQ_HDMIRX, + + RK628_IRQ_GPIO0, + RK628_IRQ_GPIO1, + RK628_IRQ_GPIO2, + RK628_IRQ_GPIO3, + RK628_IRQ_EFUSE, +}; + +static struct resource rk628_gpio_resources[] = { + DEFINE_RES_IRQ(RK628_IRQ_GPIO0), + DEFINE_RES_IRQ(RK628_IRQ_GPIO1), + DEFINE_RES_IRQ(RK628_IRQ_GPIO2), + DEFINE_RES_IRQ(RK628_IRQ_GPIO3), +}; + +static struct resource rk628_dsi0_resources[] = { + DEFINE_RES_IRQ(RK628_IRQ_DSI0), +}; + +static struct resource rk628_dsi1_resources[] = { + DEFINE_RES_IRQ(RK628_IRQ_DSI1), +}; + +static struct resource rk628_csi_resources[] = { + DEFINE_RES_IRQ(RK628_IRQ_CSI), +}; + +static struct resource rk628_gvi_resources[] = { + DEFINE_RES_IRQ(RK628_IRQ_GVI), +}; + +static struct resource rk628_hdmi_resources[] = { + DEFINE_RES_IRQ(RK628_IRQ_HDMITX), + DEFINE_RES_IRQ(RK628_IRQ_HDMITX_HPD_HIGH), + DEFINE_RES_IRQ(RK628_IRQ_HDMITX_HPD_LOW), +}; + +static struct resource rk628_hdmirx_resources[] = { + DEFINE_RES_IRQ(RK628_IRQ_HDMIRX), +}; + +static struct resource rk628_efuse_resources[] = { + DEFINE_RES_IRQ(RK628_IRQ_EFUSE), +}; + +static const struct mfd_cell rk628_devs[] = { + { + .name = "rk628-cru", + .of_compatible = "rockchip,rk628-cru", + }, { + .name = "rk628-pinctrl", + .of_compatible = "rockchip,rk628-pinctrl", + .resources = rk628_gpio_resources, + .num_resources = ARRAY_SIZE(rk628_gpio_resources), + }, { + .name = "rk628-combrxphy", + .of_compatible = "rockchip,rk628-combrxphy", + }, { + .name = "rk628-combtxphy", + .of_compatible = "rockchip,rk628-combtxphy", + }, { + .name = "rk628-csi", + .of_compatible = "rockchip,rk628-csi", + .resources = rk628_csi_resources, + .num_resources = ARRAY_SIZE(rk628_csi_resources), + }, { + .name = "rk628-hdmirx", + .of_compatible = "rockchip,rk628-hdmirx", + .resources = rk628_hdmirx_resources, + .num_resources = ARRAY_SIZE(rk628_hdmirx_resources), + }, { + .name = "rk628-dsi1", + .of_compatible = "rockchip,rk628-dsi1", + .resources = rk628_dsi1_resources, + .num_resources = ARRAY_SIZE(rk628_dsi1_resources), + }, { + .name = "rk628-dsi0", + .of_compatible = "rockchip,rk628-dsi0", + .resources = rk628_dsi0_resources, + .num_resources = ARRAY_SIZE(rk628_dsi0_resources), + }, { + .name = "rk628-rgb", + .of_compatible = "rockchip,rk628-rgb", + }, { + .name = "rk628-lvds", + .of_compatible = "rockchip,rk628-lvds", + }, { + .name = "rk628-gvi", + .of_compatible = "rockchip,rk628-gvi", + .resources = rk628_gvi_resources, + .num_resources = ARRAY_SIZE(rk628_gvi_resources), + }, { + .name = "rk628-hdmi", + .of_compatible = "rockchip,rk628-hdmi", + .resources = rk628_hdmi_resources, + .num_resources = ARRAY_SIZE(rk628_hdmi_resources), + }, { + .name = "rk628-efuse", + .of_compatible = "rockchip,rk628-efuse", + .resources = rk628_efuse_resources, + .num_resources = ARRAY_SIZE(rk628_efuse_resources), + }, { + .name = "rk628-post-process", + .of_compatible = "rockchip,rk628-post-process", + }, +}; + +static const struct regmap_irq rk628_irqs[] = { + REGMAP_IRQ_REG(RK628_IRQ_HDMITX_HPD_HIGH, 0, BIT(0)), + REGMAP_IRQ_REG(RK628_IRQ_HDMITX_HPD_LOW, 0, BIT(1)), + REGMAP_IRQ_REG(RK628_IRQ_HDMITX, 0, BIT(2)), + REGMAP_IRQ_REG(RK628_IRQ_GVI, 0, BIT(3)), + REGMAP_IRQ_REG(RK628_IRQ_DSI1, 0, BIT(4)), + REGMAP_IRQ_REG(RK628_IRQ_DSI0, 0, BIT(5)), + REGMAP_IRQ_REG(RK628_IRQ_CSI, 0, BIT(6)), + REGMAP_IRQ_REG(RK628_IRQ_HDMIRX, 0, BIT(8)), + + REGMAP_IRQ_REG(RK628_IRQ_GPIO0, 4, BIT(0)), + REGMAP_IRQ_REG(RK628_IRQ_GPIO1, 4, BIT(1)), + REGMAP_IRQ_REG(RK628_IRQ_GPIO2, 4, BIT(2)), + REGMAP_IRQ_REG(RK628_IRQ_GPIO3, 4, BIT(3)), + REGMAP_IRQ_REG(RK628_IRQ_EFUSE, 4, BIT(4)), +}; + +static struct rk628_irq_chip_data rk628_irq_chip_data = { + .name = "rk628", + .irqs = rk628_irqs, + .num_irqs = ARRAY_SIZE(rk628_irqs), + .num_regs = 2, + .irq_reg_stride = (GRF_INTR1_STATUS - GRF_INTR0_STATUS) / 4, + .reg_stride = 4, + .status_base = GRF_INTR0_STATUS, + .mask_base = GRF_INTR0_EN, + .ack_base = GRF_INTR0_CLR_EN, +}; + +static const struct regmap_config rk628_grf_regmap_config = { + .name = "grf", + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = GRF_MAX_REGISTER, + .reg_format_endian = REGMAP_ENDIAN_LITTLE, + .val_format_endian = REGMAP_ENDIAN_LITTLE, +}; + +static inline const struct regmap_irq * +irq_to_regmap_irq(struct rk628_irq_chip_data *d, int irq) +{ + return &d->irqs[irq]; +} + +static void rk628_irq_lock(struct irq_data *data) +{ + struct rk628_irq_chip_data *d = irq_data_get_irq_chip_data(data); + + mutex_lock(&d->lock); +} + +static void rk628_irq_sync_unlock(struct irq_data *data) +{ + struct rk628_irq_chip_data *d = irq_data_get_irq_chip_data(data); + int i; + u32 reg, mask, val; + + for (i = 0; i < d->num_regs; i++) { + reg = d->mask_base + (i * d->reg_stride * d->irq_reg_stride); + mask = d->mask_buf_def[i]; + val = mask << 16 | (~d->mask_buf[i] & mask); + regmap_write(d->map, reg, val); + } + + mutex_unlock(&d->lock); +} + +static void rk628_irq_enable(struct irq_data *data) +{ + struct rk628_irq_chip_data *d = irq_data_get_irq_chip_data(data); + const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq); + + d->mask_buf[irq_data->reg_offset / d->reg_stride] &= ~irq_data->mask; +} + +static void rk628_irq_disable(struct irq_data *data) +{ + struct rk628_irq_chip_data *d = irq_data_get_irq_chip_data(data); + const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq); + + d->mask_buf[irq_data->reg_offset / d->reg_stride] |= irq_data->mask; +} + +static const struct irq_chip rk628_irq_chip = { + .irq_bus_lock = rk628_irq_lock, + .irq_bus_sync_unlock = rk628_irq_sync_unlock, + .irq_disable = rk628_irq_disable, + .irq_enable = rk628_irq_enable, +}; + +static irqreturn_t rk628_irq_thread(int irq, void *data) +{ + struct rk628_irq_chip_data *d = data; + int i; + bool handled = false; + u32 reg; + + for (i = 0; i < d->num_regs; i++) { + reg = d->status_base + (i * d->reg_stride * d->irq_reg_stride); + regmap_read(d->map, reg, &d->status_buf[i]); + } + + for (i = 0; i < d->num_irqs; i++) { + if (d->status_buf[d->irqs[i].reg_offset / d->reg_stride] & d->irqs[i].mask) { + handle_nested_irq(irq_find_mapping(d->domain, i)); + handled = true; + } + } + + for (i = 0; i < d->num_regs; i++) { + if (d->status_buf[i]) { + reg = d->ack_base + (i * d->reg_stride * d->irq_reg_stride); + regmap_write(d->map, reg, + d->status_buf[i] << 16 | d->status_buf[i]); + } + } + + if (handled) + return IRQ_HANDLED; + else + return IRQ_NONE; +} + +static int rk628_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct rk628_irq_chip_data *d = h->host_data; + + irq_set_chip_data(virq, d); + irq_set_chip(virq, &d->irq_chip); + irq_set_nested_thread(virq, 1); + irq_set_parent(virq, d->irq); + irq_set_noprobe(virq); + + return 0; +} + +static const struct irq_domain_ops rk628_irq_domain_ops = { + .map = rk628_irq_map, + .xlate = irq_domain_xlate_onetwocell, +}; + +static int rk628_irq_init(struct rk628 *rk628, int irq) +{ + struct device *dev = rk628->dev; + struct rk628_irq_chip_data *d = rk628->irq_data; + struct regmap *map = rk628->grf; + u32 reg, mask, val; + int i; + int ret; + + if (d->num_regs <= 0) + return -EINVAL; + + d->status_buf = devm_kcalloc(dev, d->num_regs, sizeof(unsigned int), + GFP_KERNEL); + if (!d->status_buf) + return -ENOMEM; + + d->mask_buf = devm_kcalloc(dev, d->num_regs, sizeof(unsigned int), + GFP_KERNEL); + if (!d->mask_buf) + return -ENOMEM; + + d->mask_buf_def = devm_kcalloc(dev, d->num_regs, sizeof(unsigned int), + GFP_KERNEL); + if (!d->mask_buf_def) + return -ENOMEM; + + d->irq_chip = rk628_irq_chip; + d->irq_chip.name = d->name; + d->irq = irq; + d->map = map; + + mutex_init(&d->lock); + + for (i = 0; i < d->num_irqs; i++) + d->mask_buf_def[d->irqs[i].reg_offset / d->reg_stride] |= d->irqs[i].mask; + + /* Mask all the interrupts by default */ + for (i = 0; i < d->num_regs; i++) { + d->mask_buf[i] = d->mask_buf_def[i]; + reg = d->mask_base + (i * d->reg_stride * d->irq_reg_stride); + mask = d->mask_buf[i]; + val = mask << 16 | (~d->mask_buf[i] & mask); + regmap_write(d->map, reg, val); + } + + d->domain = irq_domain_add_linear(dev->of_node, d->num_irqs, + &rk628_irq_domain_ops, d); + if (!d->domain) { + dev_err(dev, "Failed to create IRQ domain\n"); + return -ENOMEM; + } + + ret = devm_request_threaded_irq(dev, irq, NULL, rk628_irq_thread, + IRQF_ONESHOT, d->name, d); + if (ret != 0) { + irq_domain_remove(d->domain); + dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret); + return ret; + } + + return 0; +} + +static void rk628_irq_exit(struct rk628 *rk628) +{ + struct rk628_irq_chip_data *d = rk628->irq_data; + unsigned int virq; + int hwirq; + + /* Dispose all virtual irq from irq domain before removing it */ + for (hwirq = 0; hwirq < d->num_irqs; hwirq++) { + /* Ignore hwirq if holes in the IRQ list */ + if (!d->irqs[hwirq].mask) + continue; + + /* + * Find the virtual irq of hwirq on chip and if it is + * there then dispose it + */ + virq = irq_find_mapping(d->domain, hwirq); + if (virq) + irq_dispose_mapping(virq); + } + + irq_domain_remove(d->domain); +} + +static int +rk628_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct rk628 *rk628; + int ret; + + rk628 = devm_kzalloc(dev, sizeof(*rk628), GFP_KERNEL); + if (!rk628) + return -ENOMEM; + + rk628->dev = dev; + rk628->client = client; + rk628->irq_data = &rk628_irq_chip_data; + i2c_set_clientdata(client, rk628); + + rk628->enable_gpio = devm_gpiod_get_optional(dev, "enable", + GPIOD_OUT_LOW); + if (IS_ERR(rk628->enable_gpio)) { + ret = PTR_ERR(rk628->enable_gpio); + dev_err(dev, "failed to request enable GPIO: %d\n", ret); + return ret; + } + + rk628->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(rk628->reset_gpio)) { + ret = PTR_ERR(rk628->reset_gpio); + dev_err(dev, "failed to request reset GPIO: %d\n", ret); + return ret; + } + + gpiod_set_value(rk628->enable_gpio, 1); + usleep_range(10000, 11000); + gpiod_set_value(rk628->reset_gpio, 0); + usleep_range(10000, 11000); + gpiod_set_value(rk628->reset_gpio, 1); + usleep_range(10000, 11000); + gpiod_set_value(rk628->reset_gpio, 0); + usleep_range(10000, 11000); + + rk628->grf = devm_regmap_init_i2c(client, &rk628_grf_regmap_config); + if (IS_ERR(rk628->grf)) { + ret = PTR_ERR(rk628->grf); + dev_err(dev, "failed to allocate register map: %d\n", ret); + return ret; + } + + /* selete int io function */ + ret = regmap_write(rk628->grf, GRF_GPIO3AB_SEL_CON, 0x30002000); + if (ret) { + dev_err(dev, "failed to access register: %d\n", ret); + return ret; + } + + ret = rk628_irq_init(rk628, client->irq); + if (ret) { + dev_err(dev, "failed to add IRQ chip: %d\n", ret); + return ret; + } + + ret = mfd_add_devices(dev, PLATFORM_DEVID_NONE, + rk628_devs, ARRAY_SIZE(rk628_devs), + NULL, 0, rk628->irq_data->domain); + if (ret) { + rk628_irq_exit(rk628); + dev_err(dev, "Failed to add MFD children: %d\n", ret); + return ret; + } + + return 0; +} + +static int rk628_i2c_remove(struct i2c_client *client) +{ + struct rk628 *rk628 = i2c_get_clientdata(client); + + mfd_remove_devices(rk628->dev); + rk628_irq_exit(rk628); + + return 0; +} + +static const struct of_device_id rk628_of_match[] = { + { .compatible = "rockchip,rk628", }, + {} +}; +MODULE_DEVICE_TABLE(of, rk628_of_match); + +static const struct i2c_device_id rk628_i2c_id[] = { + { "rk628", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, rk628_i2c_id); + +static struct i2c_driver rk628_i2c_driver = { + .driver = { + .name = "rk628", + .of_match_table = of_match_ptr(rk628_of_match), + }, + .probe = rk628_i2c_probe, + .remove = rk628_i2c_remove, + .id_table = rk628_i2c_id, +}; +module_i2c_driver(rk628_i2c_driver); + +MODULE_AUTHOR("Wyon Bi "); +MODULE_DESCRIPTION("Rockchip RK628 MFD driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/rk628.h b/include/linux/mfd/rk628.h new file mode 100644 index 000000000000..24a7e4b04cd6 --- /dev/null +++ b/include/linux/mfd/rk628.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 Rockchip Electronics Co. Ltd. + * + * Author: Wyon Bi + */ + +#ifndef _RK628_H +#define _RK628_H + +#include +#include +#include +#include +#include + +#define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l))) +#define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK((h), (l)) << 16)) + +#define GRF_SYSTEM_CON0 0x0000 +#define SW_VSYNC_POL_MASK BIT(26) +#define SW_VSYNC_POL(x) UPDATE(x, 26, 26) +#define SW_HSYNC_POL_MASK BIT(25) +#define SW_HSYNC_POL(x) UPDATE(x, 25, 25) +#define SW_BT_DATA_OEN_MASK BIT(9) +#define SW_BT_DATA_OEN BIT(9) +#define SW_OUTPUT_MODE_MASK GENMASK(7, 3) +#define SW_OUTPUT_MODE(x) UPDATE(x, 7, 3) +#define SW_INPUT_MODE_MASK GENMASK(2, 0) +#define SW_INPUT_MODE(x) UPDATE(x, 2, 0) +#define GRF_SYSTEM_CON1 0x0004 +#define GRF_SYSTEM_CON2 0x0008 +#define GRF_SYSTEM_CON3 0x000c +#define GRF_SCALER_CON0 0x0010 +#define SCL_VER_DOWN_MODE(x) HIWORD_UPDATE(x, 8, 8) +#define SCL_HOR_DOWN_MODE(x) HIWORD_UPDATE(x, 7, 7) +#define SCL_BIC_COE_SEL(x) HIWORD_UPDATE(x, 6, 5) +#define SCL_VER_MODE(x) HIWORD_UPDATE(x, 4, 3) +#define SCL_HOR_MODE(x) HIWORD_UPDATE(x, 2, 1) +#define SCL_EN(x) HIWORD_UPDATE(x, 0, 0) +#define GRF_SCALER_CON1 0x0014 +#define SCL_V_FACTOR(x) UPDATE(x, 31, 16) +#define SCL_H_FACTOR(x) UPDATE(x, 15, 0) +#define GRF_SCALER_CON2 0x0018 +#define DSP_FRAME_VST(x) UPDATE(x, 28, 16) +#define DSP_FRAME_HST(x) UPDATE(x, 12, 0) +#define GRF_SCALER_CON3 0x001c +#define DSP_HS_END(x) UPDATE(x, 23, 16) +#define DSP_HTOTAL(x) UPDATE(x, 12, 0) +#define GRF_SCALER_CON4 0x0020 +#define DSP_HACT_ST(x) UPDATE(x, 28, 16) +#define DSP_HACT_END(x) UPDATE(x, 12, 0) +#define GRF_SCALER_CON5 0x0024 +#define DSP_VS_END(x) UPDATE(x, 23, 16) +#define DSP_VTOTAL(x) UPDATE(x, 12, 0) +#define GRF_SCALER_CON6 0x0028 +#define DSP_VACT_ST(x) UPDATE(x, 28, 16) +#define DSP_VACT_END(x) UPDATE(x, 12, 0) +#define GRF_SCALER_CON7 0x002c +#define DSP_HBOR_ST(x) UPDATE(x, 28, 16) +#define DSP_HBOR_END(x) UPDATE(x, 12, 0) +#define GRF_SCALER_CON8 0x0030 +#define DSP_VBOR_ST(x) UPDATE(x, 28, 16) +#define DSP_VBOR_END(x) UPDATE(x, 12, 0) +#define GRF_POST_PROC_CON 0x0034 +#define SW_DCLK_OUT_INV_EN BIT(9) +#define SW_DCLK_IN_INV_EN BIT(8) +#define SW_TXPHY_REFCLK_SEL_MASK GENMASK(6, 5) +#define SW_TXPHY_REFCLK_SEL(x) UPDATE(x, 6, 5) +#define SW_HDMITX_VCLK_PLLREF_SEL_MASK BIT(4) +#define SW_HDMITX_VCLK_PLLREF_SEL(x) UPDATE(x, 4, 4) +#define SW_HDMITX_DCLK_INV_EN BIT(3) +#define SW_SPLIT_MODE(x) UPDATE(x, 1, 1) +#define SW_SPLIT_EN BIT(0) +#define GRF_CSC_CTRL_CON 0x0038 +#define GRF_LVDS_TX_CON 0x003c +#define SW_LVDS_CON_DUAL_SEL(x) HIWORD_UPDATE(x, 12, 12) +#define SW_LVDS_CON_DEN_POLARITY(x) HIWORD_UPDATE(x, 11, 11) +#define SW_LVDS_CON_HS_POLARITY(x) HIWORD_UPDATE(x, 10, 10) +#define SW_LVDS_CON_CLKINV(x) HIWORD_UPDATE(x, 9, 9) +#define SW_LVDS_STARTPHASE(x) HIWORD_UPDATE(x, 8, 8) +#define SW_LVDS_CON_STARTSEL(x) HIWORD_UPDATE(x, 7, 7) +#define SW_LVDS_CON_CHASEL(x) HIWORD_UPDATE(x, 6, 6) +#define SW_LVDS_TIE_VSYNC_VALUE(x) HIWORD_UPDATE(x, 5, 5) +#define SW_LVDS_TIE_HSYNC_VALUE(x) HIWORD_UPDATE(x, 4, 4) +#define SW_LVDS_TIE_DEN_ONLY(x) HIWORD_UPDATE(x, 3, 3) +#define SW_LVDS_CON_MSBSEL(x) HIWORD_UPDATE(x, 2, 2) +#define SW_LVDS_CON_SELECT(x) HIWORD_UPDATE(x, 1, 0) +#define GRF_RGB_DEC_CON0 0x0040 +#define SW_HRES_MASK GENMASK(28, 16) +#define SW_HRES(x) UPDATE(x, 28, 16) +#define GRF_RGB_DEC_CON1 0x0044 +#define GRF_RGB_DEC_CON2 0x0048 +#define GRF_RGB_ENC_CON 0x004c +#define GRF_MIPI_LANE_DELAY_CON0 0x0050 +#define GRF_MIPI_LANE_DELAY_CON1 0x0054 +#define GRF_BT1120_DCLK_DELAY_CON0 0x0058 +#define GRF_BT1120_DCLK_DELAY_CON1 0x005c +#define GRF_MIPI_TX0_CON 0x0060 +#define DPIUPDATECFG BIT(26) +#define DPICOLORM BIT(25) +#define DPISHUTDN BIT(24) +#define CSI_PHYRSTZ BIT(21) +#define CSI_PHYSHUTDOWNZ BIT(20) +#define FORCETXSTOPMODE(x) UPDATE(x, 19, 16) +#define FORCERXMODE(x) UPDATE(x, 15, 12) +#define PHY_TESTCLR BIT(10) +#define PHY_TESTCLK BIT(9) +#define PHY_TESTEN BIT(8) +#define PHY_TESTDIN_MASK GENMASK(7, 0) +#define PHY_TESTDIN(x) UPDATE(x, 7, 0) +#define GRF_DPHY0_STATUS 0x0064 +#define DPHY_PHYLOCK BIT(24) +#define PHY_TESTDOUT_SHIFT 8 +#define GRF_MIPI_TX1_CON 0x0068 +#define GRF_DPHY1_STATUS 0x006c +#define GRF_GPIO0AB_SEL_CON 0x0070 +#define GRF_GPIO1AB_SEL_CON 0x0074 +#define GRF_GPIO2AB_SEL_CON 0x0078 +#define GRF_GPIO2C_SEL_CON 0x007c +#define GRF_GPIO3AB_SEL_CON 0x0080 +#define GRF_GPIO2A_SMT 0x0090 +#define GRF_GPIO2B_SMT 0x0094 +#define GRF_GPIO2C_SMT 0x0098 +#define GRF_GPIO3AB_SMT 0x009c +#define GRF_GPIO0A_P_CON 0x00a0 +#define GRF_GPIO1A_P_CON 0x00a4 +#define GRF_GPIO2A_P_CON 0x00a8 +#define GRF_GPIO2B_P_CON 0x00ac +#define GRF_GPIO2C_P_CON 0x00b0 +#define GRF_GPIO3A_P_CON 0x00b4 +#define GRF_GPIO3B_P_CON 0x00b8 +#define GRF_GPIO0B_D_CON 0x00c0 +#define GRF_GPIO1B_D_CON 0x00c4 +#define GRF_GPIO2A_D0_CON 0x00c8 +#define GRF_GPIO2A_D1_CON 0x00cc +#define GRF_GPIO2B_D0_CON 0x00d0 +#define GRF_GPIO2B_D1_CON 0x00d4 +#define GRF_GPIO2C_D0_CON 0x00d8 +#define GRF_GPIO2C_D1_CON 0x00dc +#define GRF_GPIO3A_D0_CON 0x00e0 +#define GRF_GPIO3A_D1_CON 0x00e4 +#define GRF_GPIO3B_D_CON 0x00e8 +#define GRF_GPIO_SR_CON 0x00ec +#define GRF_INTR0_EN 0x0100 +#define GRF_INTR0_CLR_EN 0x0104 +#define GRF_INTR0_STATUS 0x0108 +#define GRF_INTR0_RAW_STATUS 0x010c +#define GRF_INTR1_EN 0x0110 +#define GRF_INTR1_CLR_EN 0x0114 +#define GRF_INTR1_STATUS 0x0118 +#define GRF_INTR1_RAW_STATUS 0x011c +#define GRF_SYSTEM_STATUS0 0x0120 +#define GRF_SYSTEM_STATUS3 0x012c +#define GRF_SYSTEM_STATUS4 0x0130 +#define GRF_OS_REG0 0x0140 +#define GRF_OS_REG1 0x0144 +#define GRF_OS_REG2 0x0148 +#define GRF_OS_REG3 0x014c +#define GRF_SOC_VERSION 0x0150 +#define GRF_MAX_REGISTER GRF_SOC_VERSION + +enum { + COMBTXPHY_MODULEA_EN = BIT(0), + COMBTXPHY_MODULEB_EN = BIT(1), +}; + +enum { + OUTPUT_MODE_GVI = 1, + OUTPUT_MODE_LVDS, + OUTPUT_MODE_HDMI, + OUTPUT_MODE_CSI, + OUTPUT_MODE_DSI, + OUTPUT_MODE_BT1120 = 8, + OUTPUT_MODE_RGB = 16, + OUTPUT_MODE_YUV = 24, +}; + +enum { + INPUT_MODE_HDMI, + INPUT_MODE_BT1120 = 2, + INPUT_MODE_RGB, + INPUT_MODE_YUV, +}; + +struct rk628_irq_chip_data { + const char *name; + unsigned int status_base; + unsigned int mask_base; + unsigned int ack_base; + int num_regs; + const struct regmap_irq *irqs; + int num_irqs; + struct mutex lock; + struct irq_chip irq_chip; + struct regmap *map; + struct irq_domain *domain; + int irq; + unsigned int *status_buf; + unsigned int *mask_buf; + unsigned int *mask_buf_def; + unsigned int irq_reg_stride; + unsigned int reg_stride; +}; + +struct rk628 { + struct device *dev; + struct i2c_client *client; + struct regmap *grf; + struct gpio_desc *reset_gpio; + struct gpio_desc *enable_gpio; + struct rk628_irq_chip_data *irq_data; +}; + +#endif