From 0d5d0c895ee058f6cdcb54a26126e32804c2e341 Mon Sep 17 00:00:00 2001 From: Avenger-285714 Date: Thu, 30 May 2024 11:55:07 +0800 Subject: [PATCH 1/8] Revert "arm64: i3c: phytium: Add support for S3/S4 mode" This reverts commit e0b195dd179f98c8084eb45f4a5b2af722d71d9d. --- drivers/i3c/master/i3c-master-phytium.c | 103 ------------------------ 1 file changed, 103 deletions(-) diff --git a/drivers/i3c/master/i3c-master-phytium.c b/drivers/i3c/master/i3c-master-phytium.c index 50f3f6c989951..774853c7f1942 100644 --- a/drivers/i3c/master/i3c-master-phytium.c +++ b/drivers/i3c/master/i3c-master-phytium.c @@ -23,7 +23,6 @@ #include #include #include -#include #include "../i3c_master_acpi.h" #define DEV_ID 0x0 @@ -369,8 +368,6 @@ #define I3C_CONTROL_DEFAULT_I2C_SCL (1000000) #define I3C_CONTROL_DEFAULT_I3C_SCL (1000000) -#define PHYTIUM_I3C_DEV_MAX_NUM (12) -#define PHYTIUM_I3C_CMDR_MAX_TIMES (32) struct phytium_i3c_master_caps { u32 cmdfifodepth; @@ -402,12 +399,6 @@ struct phytium_i3c_data { u8 thd_delay_ns; }; -struct phytium_i3c_slave_dev { - u32 dev_rr0; - u32 dev_rr1; - u32 dev_rr2; -}; - struct phytium_i3c_master { struct work_struct hj_work; struct i3c_master_controller base; @@ -430,13 +421,10 @@ struct phytium_i3c_master { u32 prescl0; u32 prescl1; u32 ctrl_thd_del; - u32 ctrl_info; - u32 dev_valid; struct device *dev; struct phytium_i3c_master_caps caps; unsigned long i3c_scl_lim; const struct phytium_i3c_data *devdata; - struct phytium_i3c_slave_dev devinfo[PHYTIUM_I3C_DEV_MAX_NUM]; }; static inline struct phytium_i3c_master * @@ -554,8 +542,6 @@ static void phytium_i3c_master_start_xfer_locked(struct phytium_i3c_master *mast if (!xfer) return; - phytium_i3c_master_enable(master); - writel(MST_INT_CMDD_EMP, master->regs + MST_ICR); for (i = 0; i < xfer->ncmds; i++) { struct phytium_i3c_cmd *cmd = &xfer->cmds[i]; @@ -1292,7 +1278,6 @@ static int phytium_i3c_master_bus_init(struct i3c_master_controller *m) prescl0 |= PRESCL_CTRL0_I2C(pres); writel(prescl0, master->regs + PRESCL_CTRL0); - master->prescl0 = prescl0; /* Calculate OD and PP low. */ pres_step = 1000000000 / (bus->scl_rate.i3c * 4); @@ -1301,7 +1286,6 @@ static int phytium_i3c_master_bus_init(struct i3c_master_controller *m) ncycles = 0; prescl1 = PRESCL_CTRL1_OD_LOW(ncycles); writel(prescl1, master->regs + PRESCL_CTRL1); - master->prescl1 = prescl1; } /* Get an address for the master. */ ret = i3c_master_get_free_addr(m, 0); @@ -1613,55 +1597,6 @@ static const struct acpi_device_id phytium_i3c_master_acpi_ids[] = { }; MODULE_DEVICE_TABLE(acpi, phytium_i3c_master_acpi_ids); #endif - -static void phytium_i3c_master_controller_init(struct phytium_i3c_master *master) -{ - int i; - - phytium_i3c_master_disable(master); - - writel(FLUSH_RX_FIFO | FLUSH_TX_FIFO | FLUSH_CMD_FIFO | - FLUSH_CMD_RESP, - master->regs + FLUSH_CTRL); - - writel(0xffffffff, master->regs + MST_IDR); - writel(0xffffffff, master->regs + SLV_IDR); - - writel(master->prescl0, master->regs + PRESCL_CTRL0); - writel(master->prescl1, master->regs + PRESCL_CTRL1); - - writel(IBIR_THR(1), master->regs + CMD_IBI_THR_CTRL); - writel(MST_INT_IBIR_THR, master->regs + MST_IER); - writel(master->dev_valid, master->regs + DEVS_CTRL); - - for (i = 0; i < PHYTIUM_I3C_DEV_MAX_NUM; i++) { - writel(master->devinfo[i].dev_rr0, master->regs + DEV_ID_RR0(i)); - writel(master->devinfo[i].dev_rr1, master->regs + DEV_ID_RR1(i)); - writel(master->devinfo[i].dev_rr2, master->regs + DEV_ID_RR2(i)); - } - - for (i = 0; i < PHYTIUM_I3C_CMDR_MAX_TIMES; i++) - readl(master->regs + CMDR); - - writel(master->ctrl_info, master->regs + CTRL); - - phytium_i3c_master_enable(master); -} - -static void phytium_i3c_master_store_dev(struct phytium_i3c_master *master) -{ - int i; - - master->ctrl_info = readl(master->regs + CTRL); - master->dev_valid = readl(master->regs + DEVS_CTRL); - - for (i = 0; i < PHYTIUM_I3C_DEV_MAX_NUM; i++) { - master->devinfo[i].dev_rr0 = readl(master->regs + DEV_ID_RR0(i)); - master->devinfo[i].dev_rr1 = readl(master->regs + DEV_ID_RR1(i)); - master->devinfo[i].dev_rr2 = readl(master->regs + DEV_ID_RR2(i)); - } -} - static int phytium_i3c_master_probe(struct platform_device *pdev) { struct phytium_i3c_master *master; @@ -1729,11 +1664,6 @@ static int phytium_i3c_master_probe(struct platform_device *pdev) INIT_LIST_HEAD(&master->xferqueue.list); INIT_WORK(&master->hj_work, phytium_i3c_master_hj); - phytium_i3c_master_disable(master); - - writel(FLUSH_RX_FIFO | FLUSH_TX_FIFO | FLUSH_CMD_FIFO | - FLUSH_CMD_RESP, - master->regs + FLUSH_CTRL); writel(0xffffffff, master->regs + MST_IDR); writel(0xffffffff, master->regs + SLV_IDR); ret = devm_request_irq(&pdev->dev, irq, phytium_i3c_master_interrupt, 0, @@ -1775,8 +1705,6 @@ static int phytium_i3c_master_probe(struct platform_device *pdev) if (ret) goto err_disable_sysclk; writel(readl(master->regs + CTRL) | CTRL_HJ_ACK, master->regs + CTRL); - phytium_i3c_master_store_dev(master); - return 0; err_disable_sysclk: @@ -1800,36 +1728,6 @@ static int phytium_i3c_master_remove(struct platform_device *pdev) return 0; } -static int __maybe_unused phytium_i3c_plat_suspend(struct device *dev) -{ - struct phytium_i3c_master *master = dev_get_drvdata(dev); - - - phytium_i3c_master_disable(master); - - clk_disable_unprepare(master->sysclk); - clk_disable_unprepare(master->pclk); - - return 0; -} - -static int __maybe_unused phytium_i3c_plat_resume(struct device *dev) -{ - struct phytium_i3c_master *master = dev_get_drvdata(dev); - - phytium_i3c_master_controller_init(master); - - clk_prepare_enable(master->sysclk); - clk_prepare_enable(master->pclk); - - return 0; -} - -static const struct dev_pm_ops phytium_i3c_dev_pm_ops = { - SET_LATE_SYSTEM_SLEEP_PM_OPS(phytium_i3c_plat_suspend, - phytium_i3c_plat_resume) -}; - static struct platform_driver phytium_i3c_master = { .probe = phytium_i3c_master_probe, .remove = phytium_i3c_master_remove, @@ -1837,7 +1735,6 @@ static struct platform_driver phytium_i3c_master = { .name = "phytium-i3c-master", .of_match_table = phytium_i3c_master_of_ids, .acpi_match_table = ACPI_PTR(phytium_i3c_master_acpi_ids), - .pm = &phytium_i3c_dev_pm_ops, }, }; module_platform_driver(phytium_i3c_master); From fd3648f0bd34ea71ce588ca48481095349739450 Mon Sep 17 00:00:00 2001 From: Avenger-285714 Date: Thu, 30 May 2024 11:55:07 +0800 Subject: [PATCH 2/8] Revert "arm64: i3c: phytium: Add ACPI support for i3c driver" This reverts commit f0264e4bd5b965270b5e99852bb44edfb9979de5. --- drivers/i3c/Makefile | 1 - drivers/i3c/i3c_master_acpi.c | 95 -------- drivers/i3c/i3c_master_acpi.h | 18 -- drivers/i3c/master.c | 292 +----------------------- drivers/i3c/master/i3c-master-phytium.c | 131 ++++------- include/linux/i3c/master.h | 1 - 6 files changed, 47 insertions(+), 491 deletions(-) delete mode 100644 drivers/i3c/i3c_master_acpi.c delete mode 100644 drivers/i3c/i3c_master_acpi.h diff --git a/drivers/i3c/Makefile b/drivers/i3c/Makefile index 02d9b450fb864..11982efbc6d91 100644 --- a/drivers/i3c/Makefile +++ b/drivers/i3c/Makefile @@ -1,5 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 i3c-y := device.o master.o obj-$(CONFIG_I3C) += i3c.o -i3c-$(CONFIG_ACPI) += i3c_master_acpi.o obj-$(CONFIG_I3C) += master/ diff --git a/drivers/i3c/i3c_master_acpi.c b/drivers/i3c/i3c_master_acpi.c deleted file mode 100644 index 9346d882aa552..0000000000000 --- a/drivers/i3c/i3c_master_acpi.c +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Driver for I3C ACPI Interface - * - * Copyright (C) 2021-2023 Phytium Technology Co., Ltd. - */ - -#include -#include -#include -#include -#include -#include "i3c_master_acpi.h" - -static int i3c_master_acpi_parse_val(union acpi_object *store_elements, char *method, - int count, u32 *value) -{ - int i, package_count, ret = -1; - union acpi_object *acpi_elements; - - for (i = 0; i < count; i++) { - acpi_elements = store_elements; - if (acpi_elements[i].type == ACPI_TYPE_PACKAGE) { - package_count = acpi_elements[i].package.count; - - if (package_count == 2) { - acpi_elements = acpi_elements[i].package.elements; - if (acpi_elements[0].type == ACPI_TYPE_STRING) { - if (!strcmp(acpi_elements[0].string.pointer, method)) { - *value = acpi_elements[1].integer.value; - ret = 0; - break; - } - } - } - } - } - return ret; -} - -int i3c_master_acpi_get_params(acpi_handle handle, char *method, u32 *value) -{ - struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; - acpi_status status = 0; - union acpi_object *obj; - int count, ret = -1; - - status = acpi_evaluate_object(handle, "_DSD", NULL, &buf); - if (ACPI_FAILURE(status)) { - kfree(buf.pointer); - return -2; - } - - obj = (union acpi_object *)buf.pointer; - - if (obj->type == ACPI_TYPE_PACKAGE) { - union acpi_object *acpi_elements; - union acpi_object *store_elements; - - acpi_elements = obj->package.elements; - if ((obj->package.count >= 2) && (acpi_elements[1].type == ACPI_TYPE_PACKAGE)) { - count = acpi_elements[1].package.count; - acpi_elements = acpi_elements[1].package.elements; - - store_elements = acpi_elements; - ret = i3c_master_acpi_parse_val(store_elements, method, count, value); - } - } - - kfree(buf.pointer); - return ret; -} -EXPORT_SYMBOL_GPL(i3c_master_acpi_get_params); - -void i3c_master_acpi_clk_params(acpi_handle handle, char *method, - u32 *pres_ctrl0, u32 *pres_ctrl1, u32 *thd_delay) -{ - struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; - union acpi_object *obj; - - if (ACPI_FAILURE(acpi_evaluate_object(handle, method, NULL, &buf))) - return; - - obj = (union acpi_object *)buf.pointer; - if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 3) { - const union acpi_object *objs = obj->package.elements; - - *pres_ctrl0 = (u32)objs[0].integer.value; - *pres_ctrl1 = (u32)objs[1].integer.value; - *thd_delay = (u32)objs[2].integer.value; - } - - kfree(buf.pointer); -} -EXPORT_SYMBOL_GPL(i3c_master_acpi_clk_params); diff --git a/drivers/i3c/i3c_master_acpi.h b/drivers/i3c/i3c_master_acpi.h deleted file mode 100644 index 61fa62ff12fba..0000000000000 --- a/drivers/i3c/i3c_master_acpi.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Driver for I3C ACPI Interface - * - * Copyright (C) 2021-2023 Phytium Technology Co., Ltd. - */ - -#ifndef __I3C_MASTER_ACPI_H -#define __I3C_MASTER_ACPI_H - -#include -#include - -int i3c_master_acpi_get_params(acpi_handle handle, char *method, u32 *value); -void i3c_master_acpi_clk_params(acpi_handle handle, char *method, - u32 *pres_ctrl0, u32 *pres_ctrl1, u32 *thd_delay); - -#endif diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index 826f2877d5546..0e9ff5500a777 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -5,8 +5,6 @@ * Author: Boris Brezillon */ -#include -#include #include #include #include @@ -19,25 +17,8 @@ #include #include -#ifdef CONFIG_ACPI -#include "i3c_master_acpi.h" -#endif #include "internals.h" -struct i3c_acpi_lookup { - u64 pid; - acpi_handle adapter_handle; - acpi_handle device_handle; - acpi_handle search_handle; - int n; - int index; - u32 speed; - u32 min_speed; - u32 force_speed; - u32 slave_address; - u32 lvr; -}; - static DEFINE_IDR(i3c_bus_idr); static DEFINE_MUTEX(i3c_core_lock); static int __i3c_first_dynamic_bus_num; @@ -282,88 +263,6 @@ static ssize_t modalias_show(struct device *dev, } static DEVICE_ATTR_RO(modalias); -static ssize_t reg_read_store(struct device *dev, - struct device_attribute *da, - const char *buf, size_t size) -{ - struct i3c_device *i3c = dev_to_i3cdev(dev); - struct i3c_priv_xfer xfers[2]; - u8 status = 0; - long value; - __u8 reg; - __u8 val; - - status = kstrtol(buf, 0, &value); - if (status) - return status; - - reg = (__u8)value; - - xfers[0].rnw = false; - xfers[0].len = 1; - xfers[0].data.out = ® - - xfers[1].rnw = true; - xfers[1].len = 1; - xfers[1].data.in = &val; - - i3c_bus_normaluse_lock(i3c->bus); - i3c_device_do_priv_xfers(i3c, xfers, 2); - dev_info(dev, "reg read reg =0x%x, val=%x\n", reg, val); - i3c_bus_normaluse_unlock(i3c->bus); - - return size; -} -static DEVICE_ATTR_WO(reg_read); - -static ssize_t reg_write_store(struct device *dev, - struct device_attribute *da, - const char *buf, size_t size) -{ - struct i3c_device *i3c = dev_to_i3cdev(dev); - struct i3c_priv_xfer xfers[2]; - u8 status = 0; - char *p; - char *token; - long value; - __u8 reg; - u16 val; - - p = kmalloc(size, GFP_KERNEL); - strscpy(p, buf, size); - token = strsep(&p, " "); - - if (!token) - return -EINVAL; - - status = kstrtol(token, 0, &value); - if (status) - return status; - - reg = (u8)value; - token = strsep(&p, " "); - if (!token) - return -EINVAL; - - status = kstrtol(token, 0, &value); - if (status) - return status; - - val = ((u8)value << 8) | reg; - xfers[0].rnw = false; - xfers[0].len = 2; - xfers[0].data.out = &val; - - i3c_bus_normaluse_lock(i3c->bus); - i3c_device_do_priv_xfers(i3c, xfers, 1); - dev_info(dev, "reg write reg =0x%x, val=%x\n", reg, val); - i3c_bus_normaluse_unlock(i3c->bus); - - kfree(p); - return size; -} -static DEVICE_ATTR_WO(reg_write); - static struct attribute *i3c_device_attrs[] = { &dev_attr_bcr.attr, &dev_attr_dcr.attr, @@ -371,8 +270,6 @@ static struct attribute *i3c_device_attrs[] = { &dev_attr_dynamic_address.attr, &dev_attr_hdrcap.attr, &dev_attr_modalias.attr, - &dev_attr_reg_read.attr, - &dev_attr_reg_write.attr, NULL, }; ATTRIBUTE_GROUPS(i3c_device); @@ -1624,10 +1521,9 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master) dev_set_name(&desc->dev->dev, "%d-%llx", master->bus.id, desc->info.pid); - if (desc->boardinfo) { + if (desc->boardinfo) desc->dev->dev.of_node = desc->boardinfo->of_node; - desc->dev->dev.fwnode = desc->boardinfo->fwnode; - } + ret = device_register(&desc->dev->dev); if (ret) { dev_err(&master->dev, @@ -2252,183 +2148,6 @@ static int of_populate_i3c_bus(struct i3c_master_controller *master) return 0; } -#ifdef CONFIG_ACPI -static int i3c_acpi_master_add_i2c_boardinfo(struct i3c_master_controller *master, - struct acpi_device *adev, struct i3c_acpi_lookup *look_up) -{ - struct i2c_dev_boardinfo *boardinfo; - struct device *dev = &master->dev; - u32 addr = look_up->slave_address; - - boardinfo = devm_kzalloc(dev, sizeof(*boardinfo), GFP_KERNEL); - if (!boardinfo) - return -ENOMEM; - - boardinfo->base.addr = addr; - acpi_set_modalias(adev, dev_name(&adev->dev), boardinfo->base.type, - sizeof(boardinfo->base.type)); - boardinfo->base.fwnode = acpi_fwnode_handle(adev); - - /* - * The I3C Specification does not clearly say I2C devices with 10-bit - * address are supported. These devices can't be passed properly through - * DEFSLVS command. - */ - if (boardinfo->base.flags & I2C_CLIENT_TEN) { - dev_err(dev, "I2C device with 10 bit address not supported."); - return -EOPNOTSUPP; - } - - boardinfo->lvr = look_up->lvr; - - /* If the client speed is smaller than controller speed, - * then set the controller speed to the client speed - */ - if (look_up->speed && look_up->speed < master->bus.scl_rate.i2c) - master->bus.scl_rate.i2c = look_up->speed; - - list_add_tail(&boardinfo->node, &master->boardinfo.i2c); - - return 0; -} - -static int i3c_acpi_master_add_i3c_boardinfo(struct i3c_master_controller *master, - struct acpi_device *adev, acpi_handle handle, struct i3c_acpi_lookup *look_up) -{ - struct i3c_dev_boardinfo *boardinfo; - struct device *dev = &master->dev; - enum i3c_addr_slot_status addrstatus; - u32 init_dyn_addr = 0; - - boardinfo = devm_kzalloc(dev, sizeof(*boardinfo), GFP_KERNEL); - if (!boardinfo) - return -ENOMEM; - - if (look_up->slave_address) { - if (look_up->slave_address > I3C_MAX_ADDR) - return -EINVAL; - - addrstatus = i3c_bus_get_addr_slot_status(&master->bus, look_up->slave_address); - if (addrstatus != I3C_ADDR_SLOT_FREE) - return -EINVAL; - } - - boardinfo->static_addr = look_up->slave_address; - boardinfo->pid = look_up->pid; - - if ((boardinfo->pid & GENMASK_ULL(63, 48)) || - I3C_PID_RND_LOWER_32BITS(boardinfo->pid)) - return -EINVAL; - - boardinfo->init_dyn_addr = init_dyn_addr; - boardinfo->fwnode = acpi_fwnode_handle(adev); - - /* If the client speed is smaller than controller speed, - * then set the controller speed to the client speed - */ - if (look_up->speed && look_up->speed < master->bus.scl_rate.i3c) - master->bus.scl_rate.i3c = look_up->speed; - - list_add_tail(&boardinfo->node, &master->boardinfo.i3c); - - return 0; -} - -static int i3c_acpi_master_get_resource(struct acpi_resource *ares, void *data) -{ - struct i3c_acpi_lookup *look_up = (struct i3c_acpi_lookup *)data; - struct acpi_resource_i2c_serialbus *sb; - bool ret; - - ret = i2c_acpi_get_i2c_resource(ares, &sb); - if (ret == true) { - look_up->slave_address = sb->slave_address; - look_up->speed = sb->connection_speed; - } - - return 0; -} - -static int i3c_acpi_master_get_slave_info(struct i3c_master_controller *master, - struct acpi_device *adev, struct i3c_acpi_lookup *look_up) -{ - struct list_head resource_list; - int ret; - - /* Look up for I2cSerialBus resource */ - INIT_LIST_HEAD(&resource_list); - ret = acpi_dev_get_resources(adev, &resource_list, - i3c_acpi_master_get_resource, look_up); - acpi_dev_free_resource_list(&resource_list); - - return ret; -} - - -static bool i3c_master_check_cpu_workaround(void) -{ - u32 cpu_implementor; - - cpu_implementor = read_cpuid_implementor(); - - if (cpu_implementor == ARM_CPU_IMP_PHYTIUM) - return true; - - return false; -} - -static int i3c_acpi_master_add_dev(struct acpi_device *adev, void *data) -{ - int ret = -1; - acpi_handle handle = adev->handle; - acpi_status status; - struct i3c_master_controller *master = (struct i3c_master_controller *)data; - u64 pid, lvr; - struct i3c_acpi_lookup look_up; - u32 mode_val; - - i3c_acpi_master_get_slave_info(master, adev, &look_up); - - status = acpi_evaluate_integer(handle, "_ADR", NULL, &pid); - - if (ACPI_SUCCESS(status)) - look_up.pid = pid; - else - look_up.pid = 0x202a0a0a0a0; - - if (i3c_master_check_cpu_workaround() == true) { - dev_info(&master->dev, "I3C ACPI SPECIAL KEYS\n"); - status = acpi_evaluate_integer(handle, "_LVR", NULL, &lvr); - - if (ACPI_SUCCESS(status)) - look_up.lvr = (u32)lvr; - else - look_up.lvr = 0; - - ret = i3c_master_acpi_get_params(handle, "i3c-mode", &mode_val); - if (!ret) { - if (!mode_val) - i3c_acpi_master_add_i2c_boardinfo(master, adev, &look_up); - else - i3c_acpi_master_add_i3c_boardinfo(master, adev, handle, &look_up); - } - } - return 0; -} - -static void i3c_acpi_register_devices(struct i3c_master_controller *master) -{ - struct acpi_device *adev = NULL; - - if (!has_acpi_companion(master->dev.parent)) - return; - - adev = acpi_fetch_acpi_dev(ACPI_HANDLE(master->dev.parent)); - if (adev) - acpi_dev_for_each_child(adev, i3c_acpi_master_add_dev, master); -} -#endif - static int i3c_master_i2c_adapter_xfer(struct i2c_adapter *adap, struct i2c_msg *xfers, int nxfers) { @@ -2592,7 +2311,7 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master) adap->dev.parent = master->dev.parent; adap->owner = master->dev.parent->driver->owner; adap->algo = &i3c_master_i2c_algo; - strscpy(adap->name, dev_name(master->dev.parent), sizeof(adap->name)); + strncpy(adap->name, dev_name(master->dev.parent), sizeof(adap->name)); /* FIXME: Should we allow i3c masters to override these values? */ adap->timeout = 1000; @@ -2897,7 +2616,6 @@ int i3c_master_register(struct i3c_master_controller *master, master->dev.parent = parent; master->dev.of_node = of_node_get(parent->of_node); - master->dev.fwnode = parent->fwnode; master->dev.bus = &i3c_bus_type; master->dev.type = &i3c_masterdev_type; master->dev.release = i3c_masterdev_release; @@ -2916,9 +2634,7 @@ int i3c_master_register(struct i3c_master_controller *master, ret = of_populate_i3c_bus(master); if (ret) goto err_put_dev; -#ifdef CONFIG_ACPI - i3c_acpi_register_devices(master); -#endif + list_for_each_entry(i2cbi, &master->boardinfo.i2c, node) { switch (i2cbi->lvr & I3C_LVR_I2C_INDEX_MASK) { case I3C_LVR_I2C_INDEX(0): diff --git a/drivers/i3c/master/i3c-master-phytium.c b/drivers/i3c/master/i3c-master-phytium.c index 774853c7f1942..3d863b44a8c46 100644 --- a/drivers/i3c/master/i3c-master-phytium.c +++ b/drivers/i3c/master/i3c-master-phytium.c @@ -22,8 +22,6 @@ #include #include #include -#include -#include "../i3c_master_acpi.h" #define DEV_ID 0x0 #define DEV_ID_I3C_MASTER 0x5034 @@ -366,9 +364,6 @@ #define ASF_PROTO_FAULT_MSTDDR_FAIL BIT(14) #define ASF_PROTO_FAULT_M(x) BIT(x) -#define I3C_CONTROL_DEFAULT_I2C_SCL (1000000) -#define I3C_CONTROL_DEFAULT_I3C_SCL (1000000) - struct phytium_i3c_master_caps { u32 cmdfifodepth; u32 cmdrfifodepth; @@ -417,11 +412,6 @@ struct phytium_i3c_master { void __iomem *regs; struct clk *sysclk; struct clk *pclk; - u32 sysclk_rate; - u32 prescl0; - u32 prescl1; - u32 ctrl_thd_del; - struct device *dev; struct phytium_i3c_master_caps caps; unsigned long i3c_scl_lim; const struct phytium_i3c_data *devdata; @@ -1248,45 +1238,40 @@ static int phytium_i3c_master_bus_init(struct i3c_master_controller *m) return -EINVAL; } - if (has_acpi_companion(master->dev)) { - writel(master->prescl0, master->regs + PRESCL_CTRL0); - writel(master->prescl1, master->regs + PRESCL_CTRL1); - } else { - sysclk_rate = clk_get_rate(master->sysclk); + sysclk_rate = clk_get_rate(master->sysclk); + if (!sysclk_rate) + return -EINVAL; - if (!sysclk_rate) - return -EINVAL; + pres = DIV_ROUND_UP(sysclk_rate, (bus->scl_rate.i3c * 4)) - 1; + if (pres > PRESCL_CTRL0_MAX) + return -ERANGE; - pres = DIV_ROUND_UP(sysclk_rate, (bus->scl_rate.i3c * 4)) - 1; - if (pres > PRESCL_CTRL0_MAX) - return -ERANGE; + bus->scl_rate.i3c = sysclk_rate / ((pres + 1) * 4); - bus->scl_rate.i3c = sysclk_rate / ((pres + 1) * 4); + prescl0 = PRESCL_CTRL0_I3C(pres); - prescl0 = PRESCL_CTRL0_I3C(pres); + low = ((I3C_BUS_TLOW_OD_MIN_NS * sysclk_rate) / (pres + 1)) - 2; + prescl1 = PRESCL_CTRL1_OD_LOW(low); - low = ((I3C_BUS_TLOW_OD_MIN_NS * sysclk_rate) / (pres + 1)) - 2; - prescl1 = PRESCL_CTRL1_OD_LOW(low); + max_i2cfreq = bus->scl_rate.i2c; - max_i2cfreq = bus->scl_rate.i2c; + pres = (sysclk_rate / (max_i2cfreq * 5)) - 1; + if (pres > PRESCL_CTRL0_MAX) + return -ERANGE; - pres = (sysclk_rate / (max_i2cfreq * 5)) - 1; - if (pres > PRESCL_CTRL0_MAX) - return -ERANGE; + bus->scl_rate.i2c = sysclk_rate / ((pres + 1) * 5); - bus->scl_rate.i2c = sysclk_rate / ((pres + 1) * 5); + prescl0 |= PRESCL_CTRL0_I2C(pres); + writel(prescl0, master->regs + PRESCL_CTRL0); - prescl0 |= PRESCL_CTRL0_I2C(pres); - writel(prescl0, master->regs + PRESCL_CTRL0); + /* Calculate OD and PP low. */ + pres_step = 1000000000 / (bus->scl_rate.i3c * 4); + ncycles = DIV_ROUND_UP(I3C_BUS_TLOW_OD_MIN_NS, pres_step) - 2; + if (ncycles < 0) + ncycles = 0; + prescl1 = PRESCL_CTRL1_OD_LOW(ncycles); + writel(prescl1, master->regs + PRESCL_CTRL1); - /* Calculate OD and PP low. */ - pres_step = 1000000000 / (bus->scl_rate.i3c * 4); - ncycles = DIV_ROUND_UP(I3C_BUS_TLOW_OD_MIN_NS, pres_step) - 2; - if (ncycles < 0) - ncycles = 0; - prescl1 = PRESCL_CTRL1_OD_LOW(ncycles); - writel(prescl1, master->regs + PRESCL_CTRL1); - } /* Get an address for the master. */ ret = i3c_master_get_free_addr(m, 0); if (ret < 0) @@ -1318,11 +1303,7 @@ static int phytium_i3c_master_bus_init(struct i3c_master_controller *m) * master output. This setting allows to meet this timing on master's * SoC outputs, regardless of PCB balancing. */ - if (has_acpi_companion(master->dev)) - ctrl |= CTRL_THD_DELAY(master->ctrl_thd_del); - else - ctrl |= CTRL_THD_DELAY(phytium_i3c_master_calculate_thd_delay(master)); - + ctrl |= CTRL_THD_DELAY(phytium_i3c_master_calculate_thd_delay(master)); writel(ctrl, master->regs + CTRL); phytium_i3c_master_enable(master); @@ -1590,13 +1571,6 @@ static const struct of_device_id phytium_i3c_master_of_ids[] = { { /* sentinel */ }, }; -#ifdef CONFIG_ACPI -static const struct acpi_device_id phytium_i3c_master_acpi_ids[] = { - { "PHYT0035", 0 }, - { } -}; -MODULE_DEVICE_TABLE(acpi, phytium_i3c_master_acpi_ids); -#endif static int phytium_i3c_master_probe(struct platform_device *pdev) { struct phytium_i3c_master *master; @@ -1608,53 +1582,35 @@ static int phytium_i3c_master_probe(struct platform_device *pdev) if (!master) return -ENOMEM; - master->dev = &pdev->dev; + master->devdata = of_device_get_match_data(&pdev->dev); + if (!master->devdata) + return -EINVAL; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); master->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(master->regs)) return PTR_ERR(master->regs); - if (pdev->dev.of_node) { - master->devdata = of_device_get_match_data(&pdev->dev); - - if (!master->devdata) - return -EINVAL; + master->pclk = devm_clk_get(&pdev->dev, "pclk"); + if (IS_ERR(master->pclk)) + return PTR_ERR(master->pclk); - - master->pclk = devm_clk_get(&pdev->dev, "pclk"); - if (IS_ERR(master->pclk)) - return PTR_ERR(master->pclk); - - master->sysclk = devm_clk_get(&pdev->dev, "sysclk"); - if (IS_ERR(master->sysclk)) - return PTR_ERR(master->sysclk); - - ret = clk_prepare_enable(master->pclk); - if (ret) - return ret; - - ret = clk_prepare_enable(master->sysclk); - if (ret) - goto err_disable_pclk; -#ifdef CONFIG_ACPI - } else if (has_acpi_companion(&pdev->dev)) { - i3c_master_acpi_clk_params(ACPI_HANDLE(&pdev->dev), "SCLK", &master->prescl0, - &master->prescl1, &master->ctrl_thd_del); - - if (!master->prescl0) - goto err_disable_sysclk; - - master->base.bus.scl_rate.i2c = I3C_CONTROL_DEFAULT_I2C_SCL; - master->base.bus.scl_rate.i3c = I3C_BUS_MAX_I3C_SCL_RATE; - ACPI_COMPANION_SET(master->dev, ACPI_COMPANION(&pdev->dev)); -#endif - } + master->sysclk = devm_clk_get(&pdev->dev, "sysclk"); + if (IS_ERR(master->sysclk)) + return PTR_ERR(master->sysclk); irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; + ret = clk_prepare_enable(master->pclk); + if (ret) + return ret; + + ret = clk_prepare_enable(master->sysclk); + if (ret) + goto err_disable_pclk; + if (readl(master->regs + DEV_ID) != DEV_ID_I3C_MASTER) { ret = -EINVAL; goto err_disable_sysclk; @@ -1734,7 +1690,6 @@ static struct platform_driver phytium_i3c_master = { .driver = { .name = "phytium-i3c-master", .of_match_table = phytium_i3c_master_of_ids, - .acpi_match_table = ACPI_PTR(phytium_i3c_master_acpi_ids), }, }; module_platform_driver(phytium_i3c_master); diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h index c55be28cf0918..0b52da4f23467 100644 --- a/include/linux/i3c/master.h +++ b/include/linux/i3c/master.h @@ -182,7 +182,6 @@ struct i3c_dev_boardinfo { u8 static_addr; u64 pid; struct device_node *of_node; - struct fwnode_handle *fwnode; }; /** From dbb3a4b032ce6f9c73f12650b8b0aa56d5048dc0 Mon Sep 17 00:00:00 2001 From: Avenger-285714 Date: Thu, 30 May 2024 11:55:07 +0800 Subject: [PATCH 3/8] Revert "arm64:i3c: phytium: Add support for Phytium i3c controller" This reverts commit 8f038cfe7eca086ff6d83b0e6f949d7a3d43b877. --- drivers/i3c/master/Kconfig | 9 - drivers/i3c/master/Makefile | 1 - drivers/i3c/master/i3c-master-phytium.c | 1700 ----------------------- 3 files changed, 1710 deletions(-) delete mode 100644 drivers/i3c/master/i3c-master-phytium.c diff --git a/drivers/i3c/master/Kconfig b/drivers/i3c/master/Kconfig index f39122918b187..90dee3ec55209 100644 --- a/drivers/i3c/master/Kconfig +++ b/drivers/i3c/master/Kconfig @@ -57,12 +57,3 @@ config MIPI_I3C_HCI This driver can also be built as a module. If so, the module will be called mipi-i3c-hci. - -config PHYTIUM_I3C_MASTER - tristate "Phytium I3C master driver" - depends on I3C - depends on HAS_IOMEM - depends on !(ALPHA || PARISC) - help - Enable this driver if you want to support phytium I3C master block. - diff --git a/drivers/i3c/master/Makefile b/drivers/i3c/master/Makefile index 3819a4dab6acf..3e97960160bc8 100644 --- a/drivers/i3c/master/Makefile +++ b/drivers/i3c/master/Makefile @@ -4,4 +4,3 @@ obj-$(CONFIG_DW_I3C_MASTER) += dw-i3c-master.o obj-$(CONFIG_AST2600_I3C_MASTER) += ast2600-i3c-master.o obj-$(CONFIG_SVC_I3C_MASTER) += svc-i3c-master.o obj-$(CONFIG_MIPI_I3C_HCI) += mipi-i3c-hci/ -obj-$(CONFIG_PHYTIUM_I3C_MASTER) += i3c-master-phytium.o diff --git a/drivers/i3c/master/i3c-master-phytium.c b/drivers/i3c/master/i3c-master-phytium.c deleted file mode 100644 index 3d863b44a8c46..0000000000000 --- a/drivers/i3c/master/i3c-master-phytium.c +++ /dev/null @@ -1,1700 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2022 Phytium Technology Co.,Ltd. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEV_ID 0x0 -#define DEV_ID_I3C_MASTER 0x5034 - -#define CONF_STATUS0 0x4 -#define CONF_STATUS0_CMDR_DEPTH(x) (4 << (((x) & GENMASK(31, 29)) >> 29)) -#define CONF_STATUS0_ECC_CHK BIT(28) -#define CONF_STATUS0_INTEG_CHK BIT(27) -#define CONF_STATUS0_CSR_DAP_CHK BIT(26) -#define CONF_STATUS0_TRANS_TOUT_CHK BIT(25) -#define CONF_STATUS0_PROT_FAULTS_CHK BIT(24) -#define CONF_STATUS0_GPO_NUM(x) (((x) & GENMASK(23, 16)) >> 16) -#define CONF_STATUS0_GPI_NUM(x) (((x) & GENMASK(15, 8)) >> 8) -#define CONF_STATUS0_IBIR_DEPTH(x) (4 << (((x) & GENMASK(7, 6)) >> 7)) -#define CONF_STATUS0_SUPPORTS_DDR BIT(5) -#define CONF_STATUS0_SEC_MASTER BIT(4) -#define CONF_STATUS0_DEVS_NUM(x) ((x) & GENMASK(3, 0)) - -#define CONF_STATUS1 0x8 -#define CONF_STATUS1_IBI_HW_RES(x) ((((x) & GENMASK(31, 28)) >> 28) + 1) -#define CONF_STATUS1_CMD_DEPTH(x) (4 << (((x) & GENMASK(27, 26)) >> 26)) -#define CONF_STATUS1_SLVDDR_RX_DEPTH(x) (8 << (((x) & GENMASK(25, 21)) >> 21)) -#define CONF_STATUS1_SLVDDR_TX_DEPTH(x) (8 << (((x) & GENMASK(20, 16)) >> 16)) -#define CONF_STATUS1_IBI_DEPTH(x) (2 << (((x) & GENMASK(12, 10)) >> 10)) -#define CONF_STATUS1_RX_DEPTH(x) (8 << (((x) & GENMASK(9, 5)) >> 5)) -#define CONF_STATUS1_TX_DEPTH(x) (8 << ((x) & GENMASK(4, 0))) - -#define REV_ID 0xc -#define REV_ID_VID(id) (((id) & GENMASK(31, 20)) >> 20) -#define REV_ID_PID(id) (((id) & GENMASK(19, 8)) >> 8) -#define REV_ID_REV_MAJOR(id) (((id) & GENMASK(7, 4)) >> 4) -#define REV_ID_REV_MINOR(id) ((id) & GENMASK(3, 0)) - -#define CTRL 0x10 -#define CTRL_DEV_EN BIT(31) -#define CTRL_HALT_EN BIT(30) -#define CTRL_MCS BIT(29) -#define CTRL_MCS_EN BIT(28) -#define CTRL_THD_DELAY(x) (((x) << 24) & GENMASK(25, 24)) -#define CTRL_HJ_DISEC BIT(8) -#define CTRL_MST_ACK BIT(7) -#define CTRL_HJ_ACK BIT(6) -#define CTRL_HJ_INIT BIT(5) -#define CTRL_MST_INIT BIT(4) -#define CTRL_AHDR_OPT BIT(3) -#define CTRL_PURE_BUS_MODE 0 -#define CTRL_MIXED_FAST_BUS_MODE 2 -#define CTRL_MIXED_SLOW_BUS_MODE 3 -#define CTRL_BUS_MODE_MASK GENMASK(1, 0) -#define THD_DELAY_MAX 3 - -#define PRESCL_CTRL0 0x14 -#define PRESCL_CTRL0_I2C(x) ((x) << 16) -#define PRESCL_CTRL0_I3C(x) (x) -#define PRESCL_CTRL0_MAX GENMASK(9, 0) - -#define PRESCL_CTRL1 0x18 -#define PRESCL_CTRL1_PP_LOW_MASK GENMASK(15, 8) -#define PRESCL_CTRL1_PP_LOW(x) ((x) << 8) -#define PRESCL_CTRL1_OD_LOW_MASK GENMASK(7, 0) -#define PRESCL_CTRL1_OD_LOW(x) (x) - -#define MST_IER 0x20 -#define MST_IDR 0x24 -#define MST_IMR 0x28 -#define MST_ICR 0x2c -#define MST_ISR 0x30 -#define MST_INT_HALTED BIT(18) -#define MST_INT_MR_DONE BIT(17) -#define MST_INT_IMM_COMP BIT(16) -#define MST_INT_TX_THR BIT(15) -#define MST_INT_TX_OVF BIT(14) -#define MST_INT_IBID_THR BIT(12) -#define MST_INT_IBID_UNF BIT(11) -#define MST_INT_IBIR_THR BIT(10) -#define MST_INT_IBIR_UNF BIT(9) -#define MST_INT_IBIR_OVF BIT(8) -#define MST_INT_RX_THR BIT(7) -#define MST_INT_RX_UNF BIT(6) -#define MST_INT_CMDD_EMP BIT(5) -#define MST_INT_CMDD_THR BIT(4) -#define MST_INT_CMDD_OVF BIT(3) -#define MST_INT_CMDR_THR BIT(2) -#define MST_INT_CMDR_UNF BIT(1) -#define MST_INT_CMDR_OVF BIT(0) - -#define MST_STATUS0 0x34 -#define MST_STATUS0_IDLE BIT(18) -#define MST_STATUS0_HALTED BIT(17) -#define MST_STATUS0_MASTER_MODE BIT(16) -#define MST_STATUS0_TX_FULL BIT(13) -#define MST_STATUS0_IBID_FULL BIT(12) -#define MST_STATUS0_IBIR_FULL BIT(11) -#define MST_STATUS0_RX_FULL BIT(10) -#define MST_STATUS0_CMDD_FULL BIT(9) -#define MST_STATUS0_CMDR_FULL BIT(8) -#define MST_STATUS0_TX_EMP BIT(5) -#define MST_STATUS0_IBID_EMP BIT(4) -#define MST_STATUS0_IBIR_EMP BIT(3) -#define MST_STATUS0_RX_EMP BIT(2) -#define MST_STATUS0_CMDD_EMP BIT(1) -#define MST_STATUS0_CMDR_EMP BIT(0) - -#define CMDR 0x38 -#define CMDR_NO_ERROR 0 -#define CMDR_DDR_PREAMBLE_ERROR 1 -#define CMDR_DDR_PARITY_ERROR 2 -#define CMDR_DDR_RX_FIFO_OVF 3 -#define CMDR_DDR_TX_FIFO_UNF 4 -#define CMDR_M0_ERROR 5 -#define CMDR_M1_ERROR 6 -#define CMDR_M2_ERROR 7 -#define CMDR_MST_ABORT 8 -#define CMDR_NACK_RESP 9 -#define CMDR_INVALID_DA 10 -#define CMDR_DDR_DROPPED 11 -#define CMDR_ERROR(x) (((x) & GENMASK(27, 24)) >> 24) -#define CMDR_XFER_BYTES(x) (((x) & GENMASK(19, 8)) >> 8) -#define CMDR_CMDID_HJACK_DISEC 0xfe -#define CMDR_CMDID_HJACK_ENTDAA 0xff -#define CMDR_CMDID(x) ((x) & GENMASK(7, 0)) - -#define IBIR 0x3c -#define IBIR_ACKED BIT(12) -#define IBIR_SLVID(x) (((x) & GENMASK(11, 8)) >> 8) -#define IBIR_ERROR BIT(7) -#define IBIR_XFER_BYTES(x) (((x) & GENMASK(6, 2)) >> 2) -#define IBIR_TYPE_IBI 0 -#define IBIR_TYPE_HJ 1 -#define IBIR_TYPE_MR 2 -#define IBIR_TYPE(x) ((x) & GENMASK(1, 0)) - -#define SLV_IER 0x40 -#define SLV_IDR 0x44 -#define SLV_IMR 0x48 -#define SLV_ICR 0x4c -#define SLV_ISR 0x50 -#define SLV_INT_TM BIT(20) -#define SLV_INT_ERROR BIT(19) -#define SLV_INT_EVENT_UP BIT(18) -#define SLV_INT_HJ_DONE BIT(17) -#define SLV_INT_MR_DONE BIT(16) -#define SLV_INT_DA_UPD BIT(15) -#define SLV_INT_SDR_FAIL BIT(14) -#define SLV_INT_DDR_FAIL BIT(13) -#define SLV_INT_M_RD_ABORT BIT(12) -#define SLV_INT_DDR_RX_THR BIT(11) -#define SLV_INT_DDR_TX_THR BIT(10) -#define SLV_INT_SDR_RX_THR BIT(9) -#define SLV_INT_SDR_TX_THR BIT(8) -#define SLV_INT_DDR_RX_UNF BIT(7) -#define SLV_INT_DDR_TX_OVF BIT(6) -#define SLV_INT_SDR_RX_UNF BIT(5) -#define SLV_INT_SDR_TX_OVF BIT(4) -#define SLV_INT_DDR_RD_COMP BIT(3) -#define SLV_INT_DDR_WR_COMP BIT(2) -#define SLV_INT_SDR_RD_COMP BIT(1) -#define SLV_INT_SDR_WR_COMP BIT(0) - -#define SLV_STATUS0 0x54 -#define SLV_STATUS0_REG_ADDR(s) (((s) & GENMASK(23, 16)) >> 16) -#define SLV_STATUS0_XFRD_BYTES(s) ((s) & GENMASK(15, 0)) - -#define SLV_STATUS1 0x58 -#define SLV_STATUS1_AS(s) (((s) & GENMASK(21, 20)) >> 20) -#define SLV_STATUS1_VEN_TM BIT(19) -#define SLV_STATUS1_HJ_DIS BIT(18) -#define SLV_STATUS1_MR_DIS BIT(17) -#define SLV_STATUS1_PROT_ERR BIT(16) -#define SLV_STATUS1_DA(x) (((s) & GENMASK(15, 9)) >> 9) -#define SLV_STATUS1_HAS_DA BIT(8) -#define SLV_STATUS1_DDR_RX_FULL BIT(7) -#define SLV_STATUS1_DDR_TX_FULL BIT(6) -#define SLV_STATUS1_DDR_RX_EMPTY BIT(5) -#define SLV_STATUS1_DDR_TX_EMPTY BIT(4) -#define SLV_STATUS1_SDR_RX_FULL BIT(3) -#define SLV_STATUS1_SDR_TX_FULL BIT(2) -#define SLV_STATUS1_SDR_RX_EMPTY BIT(1) -#define SLV_STATUS1_SDR_TX_EMPTY BIT(0) - -#define CMD0_FIFO 0x60 -#define CMD0_FIFO_IS_DDR BIT(31) -#define CMD0_FIFO_IS_CCC BIT(30) -#define CMD0_FIFO_BCH BIT(29) -#define XMIT_BURST_STATIC_SUBADDR 0 -#define XMIT_SINGLE_INC_SUBADDR 1 -#define XMIT_SINGLE_STATIC_SUBADDR 2 -#define XMIT_BURST_WITHOUT_SUBADDR 3 -#define CMD0_FIFO_PRIV_XMIT_MODE(m) ((m) << 27) -#define CMD0_FIFO_SBCA BIT(26) -#define CMD0_FIFO_RSBC BIT(25) -#define CMD0_FIFO_IS_10B BIT(24) -#define CMD0_FIFO_PL_LEN(l) ((l) << 12) -#define CMD0_FIFO_PL_LEN_MAX 4095 -#define CMD0_FIFO_DEV_ADDR(a) ((a) << 1) -#define CMD0_FIFO_RNW BIT(0) - -#define CMD1_FIFO 0x64 -#define CMD1_FIFO_CMDID(id) ((id) << 24) -#define CMD1_FIFO_CSRADDR(a) (a) -#define CMD1_FIFO_CCC(id) (id) - -#define TX_FIFO 0x68 - -#define IMD_CMD0 0x70 -#define IMD_CMD0_PL_LEN(l) ((l) << 12) -#define IMD_CMD0_DEV_ADDR(a) ((a) << 1) -#define IMD_CMD0_RNW BIT(0) - -#define IMD_CMD1 0x74 -#define IMD_CMD1_CCC(id) (id) - -#define IMD_DATA 0x78 -#define RX_FIFO 0x80 -#define IBI_DATA_FIFO 0x84 -#define SLV_DDR_TX_FIFO 0x88 -#define SLV_DDR_RX_FIFO 0x8c - -#define CMD_IBI_THR_CTRL 0x90 -#define IBIR_THR(t) ((t) << 24) -#define CMDR_THR(t) ((t) << 16) -#define IBI_THR(t) ((t) << 8) -#define CMD_THR(t) (t) - -#define TX_RX_THR_CTRL 0x94 -#define RX_THR(t) ((t) << 16) -#define TX_THR(t) (t) - -#define SLV_DDR_TX_RX_THR_CTRL 0x98 -#define SLV_DDR_RX_THR(t) ((t) << 16) -#define SLV_DDR_TX_THR(t) (t) - -#define FLUSH_CTRL 0x9c -#define FLUSH_IBI_RESP BIT(23) -#define FLUSH_CMD_RESP BIT(22) -#define FLUSH_SLV_DDR_RX_FIFO BIT(22) -#define FLUSH_SLV_DDR_TX_FIFO BIT(21) -#define FLUSH_IMM_FIFO BIT(20) -#define FLUSH_IBI_FIFO BIT(19) -#define FLUSH_RX_FIFO BIT(18) -#define FLUSH_TX_FIFO BIT(17) -#define FLUSH_CMD_FIFO BIT(16) - -#define TTO_PRESCL_CTRL0 0xb0 -#define TTO_PRESCL_CTRL0_DIVB(x) ((x) << 16) -#define TTO_PRESCL_CTRL0_DIVA(x) (x) - -#define TTO_PRESCL_CTRL1 0xb4 -#define TTO_PRESCL_CTRL1_DIVB(x) ((x) << 16) -#define TTO_PRESCL_CTRL1_DIVA(x) (x) - -#define DEVS_CTRL 0xb8 -#define DEVS_CTRL_DEV_CLR_SHIFT 16 -#define DEVS_CTRL_DEV_CLR_ALL GENMASK(31, 16) -#define DEVS_CTRL_DEV_CLR(dev) BIT(16 + (dev)) -#define DEVS_CTRL_DEV_ACTIVE(dev) BIT(dev) -#define DEVS_CTRL_DEVS_ACTIVE_MASK GENMASK(15, 0) -#define MAX_DEVS 16 - -#define DEV_ID_RR0(d) (0xc0 + ((d) * 0x10)) -#define DEV_ID_RR0_LVR_EXT_ADDR BIT(11) -#define DEV_ID_RR0_HDR_CAP BIT(10) -#define DEV_ID_RR0_IS_I3C BIT(9) -#define DEV_ID_RR0_DEV_ADDR_MASK (GENMASK(6, 0) | GENMASK(15, 13)) -#define DEV_ID_RR0_SET_DEV_ADDR(a) (((a) & GENMASK(6, 0)) | \ - (((a) & GENMASK(9, 7)) << 6)) -#define DEV_ID_RR0_GET_DEV_ADDR(x) ((((x) >> 1) & GENMASK(6, 0)) | \ - (((x) >> 6) & GENMASK(9, 7))) - -#define DEV_ID_RR1(d) (0xc4 + ((d) * 0x10)) -#define DEV_ID_RR1_PID_MSB(pid) (pid) - -#define DEV_ID_RR2(d) (0xc8 + ((d) * 0x10)) -#define DEV_ID_RR2_PID_LSB(pid) ((pid) << 16) -#define DEV_ID_RR2_BCR(bcr) ((bcr) << 8) -#define DEV_ID_RR2_DCR(dcr) (dcr) -#define DEV_ID_RR2_LVR(lvr) (lvr) - -#define SIR_MAP(x) (0x180 + ((x) * 4)) -#define SIR_MAP_DEV_REG(d) SIR_MAP((d) / 2) -#define SIR_MAP_DEV_SHIFT(d, fs) ((fs) + (((d) % 2) ? 16 : 0)) -#define SIR_MAP_DEV_CONF_MASK(d) (GENMASK(15, 0) << (((d) % 2) ? 16 : 0)) -#define SIR_MAP_DEV_CONF(d, c) ((c) << (((d) % 2) ? 16 : 0)) -#define DEV_ROLE_SLAVE 0 -#define DEV_ROLE_MASTER 1 -#define SIR_MAP_DEV_ROLE(role) ((role) << 14) -#define SIR_MAP_DEV_SLOW BIT(13) -#define SIR_MAP_DEV_PL(l) ((l) << 8) -#define SIR_MAP_PL_MAX GENMASK(4, 0) -#define SIR_MAP_DEV_DA(a) ((a) << 1) -#define SIR_MAP_DEV_ACK BIT(0) - -#define GPIR_WORD(x) (0x200 + ((x) * 4)) -#define GPI_REG(val, id) \ - (((val) >> (((id) % 4) * 8)) & GENMASK(7, 0)) - -#define GPOR_WORD(x) (0x220 + ((x) * 4)) -#define GPO_REG(val, id) \ - (((val) >> (((id) % 4) * 8)) & GENMASK(7, 0)) - -#define ASF_INT_STATUS 0x300 -#define ASF_INT_RAW_STATUS 0x304 -#define ASF_INT_MASK 0x308 -#define ASF_INT_TEST 0x30c -#define ASF_INT_FATAL_SELECT 0x310 -#define ASF_INTEGRITY_ERR BIT(6) -#define ASF_PROTOCOL_ERR BIT(5) -#define ASF_TRANS_TIMEOUT_ERR BIT(4) -#define ASF_CSR_ERR BIT(3) -#define ASF_DAP_ERR BIT(2) -#define ASF_SRAM_UNCORR_ERR BIT(1) -#define ASF_SRAM_CORR_ERR BIT(0) - -#define ASF_SRAM_CORR_FAULT_STATUS 0x320 -#define ASF_SRAM_UNCORR_FAULT_STATUS 0x324 -#define ASF_SRAM_CORR_FAULT_INSTANCE(x) ((x) >> 24) -#define ASF_SRAM_CORR_FAULT_ADDR(x) ((x) & GENMASK(23, 0)) - -#define ASF_SRAM_FAULT_STATS 0x328 -#define ASF_SRAM_FAULT_UNCORR_STATS(x) ((x) >> 16) -#define ASF_SRAM_FAULT_CORR_STATS(x) ((x) & GENMASK(15, 0)) - -#define ASF_TRANS_TOUT_CTRL 0x330 -#define ASF_TRANS_TOUT_EN BIT(31) -#define ASF_TRANS_TOUT_VAL(x) (x) - -#define ASF_TRANS_TOUT_FAULT_MASK 0x334 -#define ASF_TRANS_TOUT_FAULT_STATUS 0x338 -#define ASF_TRANS_TOUT_FAULT_APB BIT(3) -#define ASF_TRANS_TOUT_FAULT_SCL_LOW BIT(2) -#define ASF_TRANS_TOUT_FAULT_SCL_HIGH BIT(1) -#define ASF_TRANS_TOUT_FAULT_FSCL_HIGH BIT(0) - -#define ASF_PROTO_FAULT_MASK 0x340 -#define ASF_PROTO_FAULT_STATUS 0x344 -#define ASF_PROTO_FAULT_SLVSDR_RD_ABORT BIT(31) -#define ASF_PROTO_FAULT_SLVDDR_FAIL BIT(30) -#define ASF_PROTO_FAULT_S(x) BIT(16 + (x)) -#define ASF_PROTO_FAULT_MSTSDR_RD_ABORT BIT(15) -#define ASF_PROTO_FAULT_MSTDDR_FAIL BIT(14) -#define ASF_PROTO_FAULT_M(x) BIT(x) - -struct phytium_i3c_master_caps { - u32 cmdfifodepth; - u32 cmdrfifodepth; - u32 txfifodepth; - u32 rxfifodepth; - u32 ibirfifodepth; -}; - -struct phytium_i3c_cmd { - u32 cmd0; - u32 cmd1; - u32 tx_len; - const void *tx_buf; - u32 rx_len; - void *rx_buf; - u32 error; -}; - -struct phytium_i3c_xfer { - struct list_head node; - struct completion comp; - int ret; - unsigned int ncmds; - struct phytium_i3c_cmd cmds[]; -}; - -struct phytium_i3c_data { - u8 thd_delay_ns; -}; - -struct phytium_i3c_master { - struct work_struct hj_work; - struct i3c_master_controller base; - u32 free_rr_slots; - unsigned int maxdevs; - struct { - unsigned int num_slots; - struct i3c_dev_desc **slots; - spinlock_t lock; - } ibi; - struct { - struct list_head list; - struct phytium_i3c_xfer *cur; - spinlock_t lock; - } xferqueue; - void __iomem *regs; - struct clk *sysclk; - struct clk *pclk; - struct phytium_i3c_master_caps caps; - unsigned long i3c_scl_lim; - const struct phytium_i3c_data *devdata; -}; - -static inline struct phytium_i3c_master * -to_phytium_i3c_master(struct i3c_master_controller *master) -{ - return container_of(master, struct phytium_i3c_master, base); -} - -static void phytium_i3c_master_wr_to_tx_fifo(struct phytium_i3c_master *master, - const u8 *bytes, int nbytes) -{ - writesl(master->regs + TX_FIFO, bytes, nbytes / 4); - if (nbytes & 3) { - u32 tmp = 0; - - memcpy(&tmp, bytes + (nbytes & ~3), nbytes & 3); - writesl(master->regs + TX_FIFO, &tmp, 1); - } -} - -static void phytium_i3c_master_rd_from_rx_fifo(struct phytium_i3c_master *master, - u8 *bytes, int nbytes) -{ - readsl(master->regs + RX_FIFO, bytes, nbytes / 4); - if (nbytes & 3) { - u32 tmp; - - readsl(master->regs + RX_FIFO, &tmp, 1); - memcpy(bytes + (nbytes & ~3), &tmp, nbytes & 3); - } -} - -static bool phytium_i3c_master_supports_ccc_cmd(struct i3c_master_controller *m, - const struct i3c_ccc_cmd *cmd) -{ - if (cmd->ndests > 1) - return false; - - switch (cmd->id) { - case I3C_CCC_ENEC(true): - case I3C_CCC_ENEC(false): - case I3C_CCC_DISEC(true): - case I3C_CCC_DISEC(false): - case I3C_CCC_ENTAS(0, true): - case I3C_CCC_ENTAS(0, false): - case I3C_CCC_RSTDAA(true): - case I3C_CCC_RSTDAA(false): - case I3C_CCC_ENTDAA: - case I3C_CCC_SETMWL(true): - case I3C_CCC_SETMWL(false): - case I3C_CCC_SETMRL(true): - case I3C_CCC_SETMRL(false): - case I3C_CCC_DEFSLVS: - case I3C_CCC_ENTHDR(0): - case I3C_CCC_SETDASA: - case I3C_CCC_SETNEWDA: - case I3C_CCC_GETMWL: - case I3C_CCC_GETMRL: - case I3C_CCC_GETPID: - case I3C_CCC_GETBCR: - case I3C_CCC_GETDCR: - case I3C_CCC_GETSTATUS: - case I3C_CCC_GETACCMST: - case I3C_CCC_GETMXDS: - case I3C_CCC_GETHDRCAP: - return true; - default: - break; - } - - return false; -} - -static int phytium_i3c_master_disable(struct phytium_i3c_master *master) -{ - u32 status; - - writel(readl(master->regs + CTRL) & ~CTRL_DEV_EN, master->regs + CTRL); - - return readl_poll_timeout(master->regs + MST_STATUS0, status, - status & MST_STATUS0_IDLE, 10, 1000000); -} - -static void phytium_i3c_master_enable(struct phytium_i3c_master *master) -{ - writel(readl(master->regs + CTRL) | CTRL_DEV_EN, master->regs + CTRL); -} - -static struct phytium_i3c_xfer * -phytium_i3c_master_alloc_xfer(struct phytium_i3c_master *master, unsigned int ncmds) -{ - struct phytium_i3c_xfer *xfer; - - xfer = kzalloc(struct_size(xfer, cmds, ncmds), GFP_KERNEL); - if (!xfer) - return NULL; - - INIT_LIST_HEAD(&xfer->node); - xfer->ncmds = ncmds; - xfer->ret = -ETIMEDOUT; - - return xfer; -} - -static void phytium_i3c_master_free_xfer(struct phytium_i3c_xfer *xfer) -{ - kfree(xfer); -} - -static void phytium_i3c_master_start_xfer_locked(struct phytium_i3c_master *master) -{ - struct phytium_i3c_xfer *xfer = master->xferqueue.cur; - unsigned int i; - - if (!xfer) - return; - - writel(MST_INT_CMDD_EMP, master->regs + MST_ICR); - for (i = 0; i < xfer->ncmds; i++) { - struct phytium_i3c_cmd *cmd = &xfer->cmds[i]; - - phytium_i3c_master_wr_to_tx_fifo(master, cmd->tx_buf, - cmd->tx_len); - } - for (i = 0; i < xfer->ncmds; i++) { - struct phytium_i3c_cmd *cmd = &xfer->cmds[i]; - - writel(cmd->cmd1 | CMD1_FIFO_CMDID(i), - master->regs + CMD1_FIFO); - writel(cmd->cmd0, master->regs + CMD0_FIFO); - } - - writel(readl(master->regs + CTRL) | CTRL_MCS, - master->regs + CTRL); - writel(MST_INT_CMDD_EMP, master->regs + MST_IER); -} - -static void phytium_i3c_master_end_xfer_locked(struct phytium_i3c_master *master, - u32 isr) -{ - struct phytium_i3c_xfer *xfer = master->xferqueue.cur; - int i, ret = 0; - u32 status0; - - if (!xfer) - return; - - if (!(isr & MST_INT_CMDD_EMP)) - return; - - writel(MST_INT_CMDD_EMP, master->regs + MST_IDR); - - for (status0 = readl(master->regs + MST_STATUS0); - !(status0 & MST_STATUS0_CMDR_EMP); - status0 = readl(master->regs + MST_STATUS0)) { - struct phytium_i3c_cmd *cmd; - u32 cmdr, rx_len, id; - - cmdr = readl(master->regs + CMDR); - id = CMDR_CMDID(cmdr); - if (id == CMDR_CMDID_HJACK_DISEC || - id == CMDR_CMDID_HJACK_ENTDAA || - WARN_ON(id >= xfer->ncmds)) - continue; - - cmd = &xfer->cmds[CMDR_CMDID(cmdr)]; - rx_len = min_t(u32, CMDR_XFER_BYTES(cmdr), cmd->rx_len); - phytium_i3c_master_rd_from_rx_fifo(master, cmd->rx_buf, rx_len); - cmd->error = CMDR_ERROR(cmdr); - } - - for (i = 0; i < xfer->ncmds; i++) { - switch (xfer->cmds[i].error) { - case CMDR_NO_ERROR: - break; - - case CMDR_DDR_PREAMBLE_ERROR: - case CMDR_DDR_PARITY_ERROR: - case CMDR_M0_ERROR: - case CMDR_M1_ERROR: - case CMDR_M2_ERROR: - case CMDR_MST_ABORT: - case CMDR_NACK_RESP: - case CMDR_DDR_DROPPED: - ret = -EIO; - break; - - case CMDR_DDR_RX_FIFO_OVF: - case CMDR_DDR_TX_FIFO_UNF: - ret = -ENOSPC; - break; - - case CMDR_INVALID_DA: - default: - ret = -EINVAL; - break; - } - } - - xfer->ret = ret; - complete(&xfer->comp); - - xfer = list_first_entry_or_null(&master->xferqueue.list, - struct phytium_i3c_xfer, node); - if (xfer) - list_del_init(&xfer->node); - - master->xferqueue.cur = xfer; - phytium_i3c_master_start_xfer_locked(master); -} - -static void phytium_i3c_master_queue_xfer(struct phytium_i3c_master *master, - struct phytium_i3c_xfer *xfer) -{ - unsigned long flags; - - init_completion(&xfer->comp); - spin_lock_irqsave(&master->xferqueue.lock, flags); - if (master->xferqueue.cur) { - list_add_tail(&xfer->node, &master->xferqueue.list); - } else { - master->xferqueue.cur = xfer; - phytium_i3c_master_start_xfer_locked(master); - } - spin_unlock_irqrestore(&master->xferqueue.lock, flags); -} - -static void phytium_i3c_master_unqueue_xfer(struct phytium_i3c_master *master, - struct phytium_i3c_xfer *xfer) -{ - unsigned long flags; - - spin_lock_irqsave(&master->xferqueue.lock, flags); - if (master->xferqueue.cur == xfer) { - u32 status; - - writel(readl(master->regs + CTRL) & ~CTRL_DEV_EN, - master->regs + CTRL); - readl_poll_timeout_atomic(master->regs + MST_STATUS0, status, - status & MST_STATUS0_IDLE, 10, - 1000000); - master->xferqueue.cur = NULL; - writel(FLUSH_RX_FIFO | FLUSH_TX_FIFO | FLUSH_CMD_FIFO | - FLUSH_CMD_RESP, - master->regs + FLUSH_CTRL); - writel(MST_INT_CMDD_EMP, master->regs + MST_IDR); - writel(readl(master->regs + CTRL) | CTRL_DEV_EN, - master->regs + CTRL); - } else { - list_del_init(&xfer->node); - } - spin_unlock_irqrestore(&master->xferqueue.lock, flags); -} - -static enum i3c_error_code phytium_i3c_cmd_get_err(struct phytium_i3c_cmd *cmd) -{ - switch (cmd->error) { - case CMDR_M0_ERROR: - return I3C_ERROR_M0; - - case CMDR_M1_ERROR: - return I3C_ERROR_M1; - - case CMDR_M2_ERROR: - case CMDR_NACK_RESP: - return I3C_ERROR_M2; - - default: - break; - } - - return I3C_ERROR_UNKNOWN; -} - -static int phytium_i3c_master_send_ccc_cmd(struct i3c_master_controller *m, - struct i3c_ccc_cmd *cmd) -{ - struct phytium_i3c_master *master = to_phytium_i3c_master(m); - struct phytium_i3c_xfer *xfer; - struct phytium_i3c_cmd *ccmd; - int ret; - - xfer = phytium_i3c_master_alloc_xfer(master, 1); - if (!xfer) - return -ENOMEM; - - ccmd = xfer->cmds; - ccmd->cmd1 = CMD1_FIFO_CCC(cmd->id); - ccmd->cmd0 = CMD0_FIFO_IS_CCC | - CMD0_FIFO_PL_LEN(cmd->dests[0].payload.len); - - if (cmd->id & I3C_CCC_DIRECT) - ccmd->cmd0 |= CMD0_FIFO_DEV_ADDR(cmd->dests[0].addr); - - if (cmd->rnw) { - ccmd->cmd0 |= CMD0_FIFO_RNW; - ccmd->rx_buf = cmd->dests[0].payload.data; - ccmd->rx_len = cmd->dests[0].payload.len; - } else { - ccmd->tx_buf = cmd->dests[0].payload.data; - ccmd->tx_len = cmd->dests[0].payload.len; - } - - phytium_i3c_master_queue_xfer(master, xfer); - if (!wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000))) - phytium_i3c_master_unqueue_xfer(master, xfer); - - /*GETMXDS format 1 need retransmission*/ - if ((xfer->ret) && (cmd->id == I3C_CCC_GETMXDS)) { - if (cmd->dests[0].payload.len == 5) { - cmd->dests[0].payload.len = 2; - ccmd->rx_len = cmd->dests[0].payload.len; - ccmd->cmd0 &= 0xfff000fff; - ccmd->cmd0 |= CMD0_FIFO_PL_LEN(cmd->dests[0].payload.len); - phytium_i3c_master_queue_xfer(master, xfer); - if (!wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000))) - phytium_i3c_master_unqueue_xfer(master, xfer); - } - } - ret = xfer->ret; - cmd->err = phytium_i3c_cmd_get_err(&xfer->cmds[0]); - phytium_i3c_master_free_xfer(xfer); - - return ret; -} - -static int phytium_i3c_master_priv_xfers(struct i3c_dev_desc *dev, - struct i3c_priv_xfer *xfers, - int nxfers) -{ - struct i3c_master_controller *m = i3c_dev_get_master(dev); - struct phytium_i3c_master *master = to_phytium_i3c_master(m); - int txslots = 0, rxslots = 0, i, ret; - struct phytium_i3c_xfer *phytium_xfer; - - for (i = 0; i < nxfers; i++) { - if (xfers[i].len > CMD0_FIFO_PL_LEN_MAX) - return -EOPNOTSUPP; - } - - if (!nxfers) - return 0; - - if (nxfers > master->caps.cmdfifodepth || - nxfers > master->caps.cmdrfifodepth) - return -EOPNOTSUPP; - - /* - * First make sure that all transactions (block of transfers separated - * by a STOP marker) fit in the FIFOs. - */ - for (i = 0; i < nxfers; i++) { - if (xfers[i].rnw) - rxslots += DIV_ROUND_UP(xfers[i].len, 4); - else - txslots += DIV_ROUND_UP(xfers[i].len, 4); - } - - if (rxslots > master->caps.rxfifodepth || - txslots > master->caps.txfifodepth) - return -EOPNOTSUPP; - - phytium_xfer = phytium_i3c_master_alloc_xfer(master, nxfers); - if (!phytium_xfer) - return -ENOMEM; - - for (i = 0; i < nxfers; i++) { - struct phytium_i3c_cmd *ccmd = &phytium_xfer->cmds[i]; - u32 pl_len = xfers[i].len; - - ccmd->cmd0 = CMD0_FIFO_DEV_ADDR(dev->info.dyn_addr) | - CMD0_FIFO_PRIV_XMIT_MODE(XMIT_BURST_WITHOUT_SUBADDR); - - if (xfers[i].rnw) { - ccmd->cmd0 |= CMD0_FIFO_RNW; - ccmd->rx_buf = xfers[i].data.in; - ccmd->rx_len = xfers[i].len; - pl_len++; - } else { - ccmd->tx_buf = xfers[i].data.out; - ccmd->tx_len = xfers[i].len; - } - - ccmd->cmd0 |= CMD0_FIFO_PL_LEN(pl_len); - - if (i < nxfers - 1) - ccmd->cmd0 |= CMD0_FIFO_RSBC; - - if (!i) - ccmd->cmd0 |= CMD0_FIFO_BCH; - } - - phytium_i3c_master_queue_xfer(master, phytium_xfer); - if (!wait_for_completion_timeout(&phytium_xfer->comp, - msecs_to_jiffies(1000))) - phytium_i3c_master_unqueue_xfer(master, phytium_xfer); - - ret = phytium_xfer->ret; - - for (i = 0; i < nxfers; i++) - xfers[i].err = phytium_i3c_cmd_get_err(&phytium_xfer->cmds[i]); - - phytium_i3c_master_free_xfer(phytium_xfer); - - return ret; -} - -static int phytium_i3c_master_i2c_xfers(struct i2c_dev_desc *dev, - const struct i2c_msg *xfers, int nxfers) -{ - struct i3c_master_controller *m = i2c_dev_get_master(dev); - struct phytium_i3c_master *master = to_phytium_i3c_master(m); - unsigned int nrxwords = 0, ntxwords = 0; - struct phytium_i3c_xfer *xfer; - int i, ret = 0; - - if (nxfers > master->caps.cmdfifodepth) - return -EOPNOTSUPP; - - for (i = 0; i < nxfers; i++) { - if (xfers[i].len > CMD0_FIFO_PL_LEN_MAX) - return -EOPNOTSUPP; - - if (xfers[i].flags & I2C_M_RD) - nrxwords += DIV_ROUND_UP(xfers[i].len, 4); - else - ntxwords += DIV_ROUND_UP(xfers[i].len, 4); - } - - if (ntxwords > master->caps.txfifodepth || - nrxwords > master->caps.rxfifodepth) - return -EOPNOTSUPP; - - xfer = phytium_i3c_master_alloc_xfer(master, nxfers); - if (!xfer) - return -ENOMEM; - - for (i = 0; i < nxfers; i++) { - struct phytium_i3c_cmd *ccmd = &xfer->cmds[i]; - - ccmd->cmd0 = CMD0_FIFO_DEV_ADDR(xfers[i].addr) | - CMD0_FIFO_PL_LEN(xfers[i].len) | - CMD0_FIFO_PRIV_XMIT_MODE(XMIT_BURST_WITHOUT_SUBADDR); - - if (xfers[i].flags & I2C_M_TEN) - ccmd->cmd0 |= CMD0_FIFO_IS_10B; - - if (xfers[i].flags & I2C_M_RD) { - ccmd->cmd0 |= CMD0_FIFO_RNW; - ccmd->rx_buf = xfers[i].buf; - ccmd->rx_len = xfers[i].len; - } else { - ccmd->tx_buf = xfers[i].buf; - ccmd->tx_len = xfers[i].len; - } - } - - phytium_i3c_master_queue_xfer(master, xfer); - if (!wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000))) - phytium_i3c_master_unqueue_xfer(master, xfer); - - ret = xfer->ret; - phytium_i3c_master_free_xfer(xfer); - - return ret; -} - -struct phytium_i3c_i2c_dev_data { - u16 id; - s16 ibi; - struct i3c_generic_ibi_pool *ibi_pool; -}; - -static u32 prepare_rr0_dev_address(u32 addr) -{ - u32 ret = (addr << 1) & 0xff; - - /* RR0[7:1] = addr[6:0] */ - ret |= (addr & GENMASK(6, 0)) << 1; - - /* RR0[15:13] = addr[9:7] */ - ret |= (addr & GENMASK(9, 7)) << 6; - - /* RR0[0] = ~XOR(addr[6:0]) */ - if (!(hweight8(addr & 0x7f) & 1)) - ret |= 1; - - return ret; -} - -static void phytium_i3c_master_upd_i3c_addr(struct i3c_dev_desc *dev) -{ - struct i3c_master_controller *m = i3c_dev_get_master(dev); - struct phytium_i3c_master *master = to_phytium_i3c_master(m); - struct phytium_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); - u32 rr; - - rr = prepare_rr0_dev_address(dev->info.dyn_addr ? - dev->info.dyn_addr : - dev->info.static_addr); - writel(DEV_ID_RR0_IS_I3C | rr, master->regs + DEV_ID_RR0(data->id)); -} - -static int phytium_i3c_master_get_rr_slot(struct phytium_i3c_master *master, - u8 dyn_addr) -{ - unsigned long activedevs; - u32 rr; - int i; - - if (!dyn_addr) { - if (!master->free_rr_slots) - return -ENOSPC; - - return ffs(master->free_rr_slots) - 1; - } - - activedevs = readl(master->regs + DEVS_CTRL) & DEVS_CTRL_DEVS_ACTIVE_MASK; - activedevs &= ~BIT(0); - - for_each_set_bit(i, &activedevs, master->maxdevs + 1) { - rr = readl(master->regs + DEV_ID_RR0(i)); - if (!(rr & DEV_ID_RR0_IS_I3C) || - DEV_ID_RR0_GET_DEV_ADDR(rr) != dyn_addr) - continue; - - return i; - } - - return -EINVAL; -} - -static int phytium_i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev, - u8 old_dyn_addr) -{ - phytium_i3c_master_upd_i3c_addr(dev); - - return 0; -} - -static int phytium_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev) -{ - struct i3c_master_controller *m = i3c_dev_get_master(dev); - struct phytium_i3c_master *master = to_phytium_i3c_master(m); - struct phytium_i3c_i2c_dev_data *data; - int slot; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - slot = phytium_i3c_master_get_rr_slot(master, dev->info.dyn_addr); - if (slot < 0) { - kfree(data); - return slot; - } - - data->ibi = -1; - data->id = slot; - i3c_dev_set_master_data(dev, data); - master->free_rr_slots &= ~BIT(slot); - - if (!dev->info.dyn_addr) { - phytium_i3c_master_upd_i3c_addr(dev); - writel(readl(master->regs + DEVS_CTRL) | - DEVS_CTRL_DEV_ACTIVE(data->id), - master->regs + DEVS_CTRL); - } - - return 0; -} - -static void phytium_i3c_master_detach_i3c_dev(struct i3c_dev_desc *dev) -{ - struct i3c_master_controller *m = i3c_dev_get_master(dev); - struct phytium_i3c_master *master = to_phytium_i3c_master(m); - struct phytium_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); - - writel(readl(master->regs + DEVS_CTRL) | - DEVS_CTRL_DEV_CLR(data->id), - master->regs + DEVS_CTRL); - - i3c_dev_set_master_data(dev, NULL); - master->free_rr_slots |= BIT(data->id); - kfree(data); -} - -static int phytium_i3c_master_attach_i2c_dev(struct i2c_dev_desc *dev) -{ - struct i3c_master_controller *m = i2c_dev_get_master(dev); - struct phytium_i3c_master *master = to_phytium_i3c_master(m); - struct phytium_i3c_i2c_dev_data *data; - int slot; - - slot = phytium_i3c_master_get_rr_slot(master, 0); - if (slot < 0) - return slot; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->id = slot; - master->free_rr_slots &= ~BIT(slot); - i2c_dev_set_master_data(dev, data); - - writel(prepare_rr0_dev_address(dev->addr), - master->regs + DEV_ID_RR0(data->id)); - writel(dev->lvr, master->regs + DEV_ID_RR2(data->id)); - writel(readl(master->regs + DEVS_CTRL) | - DEVS_CTRL_DEV_ACTIVE(data->id), - master->regs + DEVS_CTRL); - - return 0; -} - -static void phytium_i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev) -{ - struct i3c_master_controller *m = i2c_dev_get_master(dev); - struct phytium_i3c_master *master = to_phytium_i3c_master(m); - struct phytium_i3c_i2c_dev_data *data = i2c_dev_get_master_data(dev); - - writel(readl(master->regs + DEVS_CTRL) | - DEVS_CTRL_DEV_CLR(data->id), - master->regs + DEVS_CTRL); - master->free_rr_slots |= BIT(data->id); - - i2c_dev_set_master_data(dev, NULL); - kfree(data); -} - -static void phytium_i3c_master_bus_cleanup(struct i3c_master_controller *m) -{ - struct phytium_i3c_master *master = to_phytium_i3c_master(m); - - phytium_i3c_master_disable(master); -} - -static void phytium_i3c_master_dev_rr_to_info(struct phytium_i3c_master *master, - unsigned int slot, - struct i3c_device_info *info) -{ - u32 rr; - - memset(info, 0, sizeof(*info)); - rr = readl(master->regs + DEV_ID_RR0(slot)); - info->dyn_addr = DEV_ID_RR0_GET_DEV_ADDR(rr); - rr = readl(master->regs + DEV_ID_RR2(slot)); - info->dcr = rr; - info->bcr = rr >> 8; - info->pid = rr >> 16; - info->pid |= (u64)readl(master->regs + DEV_ID_RR1(slot)) << 16; -} - -static void phytium_i3c_master_upd_i3c_scl_lim(struct phytium_i3c_master *master) -{ - struct i3c_master_controller *m = &master->base; - unsigned long i3c_lim_period, pres_step, ncycles; - struct i3c_bus *bus = i3c_master_get_bus(m); - unsigned long new_i3c_scl_lim = 0; - struct i3c_dev_desc *dev; - u32 prescl1, ctrl; - - i3c_bus_for_each_i3cdev(bus, dev) { - unsigned long max_fscl; - - max_fscl = max(I3C_CCC_MAX_SDR_FSCL(dev->info.max_read_ds), - I3C_CCC_MAX_SDR_FSCL(dev->info.max_write_ds)); - switch (max_fscl) { - case I3C_SDR1_FSCL_8MHZ: - max_fscl = 8000000; - break; - case I3C_SDR2_FSCL_6MHZ: - max_fscl = 6000000; - break; - case I3C_SDR3_FSCL_4MHZ: - max_fscl = 4000000; - break; - case I3C_SDR4_FSCL_2MHZ: - max_fscl = 2000000; - break; - case I3C_SDR0_FSCL_MAX: - default: - max_fscl = 0; - break; - } - - if (max_fscl && - (new_i3c_scl_lim > max_fscl || !new_i3c_scl_lim)) - new_i3c_scl_lim = max_fscl; - } - - /* Only update PRESCL_CTRL1 if the I3C SCL limitation has changed. */ - if (new_i3c_scl_lim == master->i3c_scl_lim) - return; - master->i3c_scl_lim = new_i3c_scl_lim; - if (!new_i3c_scl_lim) - return; - pres_step = 1000000000UL / (bus->scl_rate.i3c * 4); - - /* Configure PP_LOW to meet I3C slave limitations. */ - prescl1 = readl(master->regs + PRESCL_CTRL1) & - ~PRESCL_CTRL1_PP_LOW_MASK; - ctrl = readl(master->regs + CTRL); - - i3c_lim_period = DIV_ROUND_UP(1000000000, master->i3c_scl_lim); - ncycles = DIV_ROUND_UP(i3c_lim_period, pres_step); - if (ncycles < 4) - ncycles = 0; - else - ncycles -= 4; - - prescl1 |= PRESCL_CTRL1_PP_LOW(ncycles); - - /* Disable I3C master before updating PRESCL_CTRL1. */ - if (ctrl & CTRL_DEV_EN) - phytium_i3c_master_disable(master); - - writel(prescl1, master->regs + PRESCL_CTRL1); - - if (ctrl & CTRL_DEV_EN) - phytium_i3c_master_enable(master); -} - -static int phytium_i3c_master_do_daa(struct i3c_master_controller *m) -{ - struct phytium_i3c_master *master = to_phytium_i3c_master(m); - unsigned long olddevs, newdevs; - int ret, slot; - u8 addrs[MAX_DEVS] = { }; - u8 last_addr = 0; - - olddevs = readl(master->regs + DEVS_CTRL) & DEVS_CTRL_DEVS_ACTIVE_MASK; - olddevs |= BIT(0); - - /* Prepare RR slots before launching DAA. */ - for_each_clear_bit(slot, &olddevs, master->maxdevs + 1) { - ret = i3c_master_get_free_addr(m, last_addr + 1); - if (ret < 0) - return -ENOSPC; - - last_addr = ret; - addrs[slot] = last_addr; - writel(prepare_rr0_dev_address(last_addr) | DEV_ID_RR0_IS_I3C, - master->regs + DEV_ID_RR0(slot)); - writel(0, master->regs + DEV_ID_RR1(slot)); - writel(0, master->regs + DEV_ID_RR2(slot)); - } - - ret = i3c_master_entdaa_locked(&master->base); - if (ret && ret != I3C_ERROR_M2) - return ret; - - newdevs = readl(master->regs + DEVS_CTRL) & DEVS_CTRL_DEVS_ACTIVE_MASK; - newdevs &= ~olddevs; - - /* - * Clear all retaining registers filled during DAA. We already - * have the addressed assigned to them in the addrs array. - */ - for_each_set_bit(slot, &newdevs, master->maxdevs + 1) - i3c_master_add_i3c_dev_locked(m, addrs[slot]); - - /* - * Clear slots that ended up not being used. Can be caused by I3C - * device creation failure or when the I3C device was already known - * by the system but with a different address (in this case the device - * already has a slot and does not need a new one). - */ - writel(readl(master->regs + DEVS_CTRL) | - master->free_rr_slots << DEVS_CTRL_DEV_CLR_SHIFT, - master->regs + DEVS_CTRL); - i3c_master_defslvs_locked(&master->base); - - phytium_i3c_master_upd_i3c_scl_lim(master); - - /* Unmask Hot-Join and Mastership request interrupts. */ - i3c_master_enec_locked(m, I3C_BROADCAST_ADDR, - I3C_CCC_EVENT_HJ | I3C_CCC_EVENT_MR); - - return 0; -} - -static u8 phytium_i3c_master_calculate_thd_delay(struct phytium_i3c_master *master) -{ - unsigned long sysclk_rate = clk_get_rate(master->sysclk); - u8 thd_delay = DIV_ROUND_UP(master->devdata->thd_delay_ns, - (NSEC_PER_SEC / sysclk_rate)); - - /* Every value greater than 3 is not valid. */ - if (thd_delay > THD_DELAY_MAX) - thd_delay = THD_DELAY_MAX; - - /* CTLR_THD_DEL value is encoded. */ - return (THD_DELAY_MAX - thd_delay); -} - -static int phytium_i3c_master_bus_init(struct i3c_master_controller *m) -{ - struct phytium_i3c_master *master = to_phytium_i3c_master(m); - unsigned long pres_step, sysclk_rate, max_i2cfreq; - struct i3c_bus *bus = i3c_master_get_bus(m); - u32 ctrl, prescl0, prescl1, pres, low; - struct i3c_device_info info = { }; - int ret, ncycles; - - switch (bus->mode) { - case I3C_BUS_MODE_PURE: - ctrl = CTRL_PURE_BUS_MODE; - break; - - case I3C_BUS_MODE_MIXED_FAST: - ctrl = CTRL_MIXED_FAST_BUS_MODE; - break; - - case I3C_BUS_MODE_MIXED_SLOW: - ctrl = CTRL_MIXED_SLOW_BUS_MODE; - break; - - default: - return -EINVAL; - } - - sysclk_rate = clk_get_rate(master->sysclk); - if (!sysclk_rate) - return -EINVAL; - - pres = DIV_ROUND_UP(sysclk_rate, (bus->scl_rate.i3c * 4)) - 1; - if (pres > PRESCL_CTRL0_MAX) - return -ERANGE; - - bus->scl_rate.i3c = sysclk_rate / ((pres + 1) * 4); - - prescl0 = PRESCL_CTRL0_I3C(pres); - - low = ((I3C_BUS_TLOW_OD_MIN_NS * sysclk_rate) / (pres + 1)) - 2; - prescl1 = PRESCL_CTRL1_OD_LOW(low); - - max_i2cfreq = bus->scl_rate.i2c; - - pres = (sysclk_rate / (max_i2cfreq * 5)) - 1; - if (pres > PRESCL_CTRL0_MAX) - return -ERANGE; - - bus->scl_rate.i2c = sysclk_rate / ((pres + 1) * 5); - - prescl0 |= PRESCL_CTRL0_I2C(pres); - writel(prescl0, master->regs + PRESCL_CTRL0); - - /* Calculate OD and PP low. */ - pres_step = 1000000000 / (bus->scl_rate.i3c * 4); - ncycles = DIV_ROUND_UP(I3C_BUS_TLOW_OD_MIN_NS, pres_step) - 2; - if (ncycles < 0) - ncycles = 0; - prescl1 = PRESCL_CTRL1_OD_LOW(ncycles); - writel(prescl1, master->regs + PRESCL_CTRL1); - - /* Get an address for the master. */ - ret = i3c_master_get_free_addr(m, 0); - if (ret < 0) - return ret; - - writel(prepare_rr0_dev_address(ret) | DEV_ID_RR0_IS_I3C, - master->regs + DEV_ID_RR0(0)); - - phytium_i3c_master_dev_rr_to_info(master, 0, &info); - if (info.bcr & I3C_BCR_HDR_CAP) - info.hdr_cap = I3C_CCC_HDR_MODE(I3C_HDR_DDR); - - ret = i3c_master_set_info(&master->base, &info); - if (ret) - return ret; - - /* - * Enable Hot-Join, and, when a Hot-Join request happens, disable all - * events coming from this device. - * - * We will issue ENTDAA afterwards from the threaded IRQ handler. - */ - - ctrl |= CTRL_HJ_DISEC | CTRL_MCS_EN; - /* - * Configure data hold delay based on device-specific data. - * - * MIPI I3C Specification 1.0 defines non-zero minimal tHD_PP timing on - * master output. This setting allows to meet this timing on master's - * SoC outputs, regardless of PCB balancing. - */ - ctrl |= CTRL_THD_DELAY(phytium_i3c_master_calculate_thd_delay(master)); - writel(ctrl, master->regs + CTRL); - - phytium_i3c_master_enable(master); - - return 0; -} - -static void phytium_i3c_master_handle_ibi(struct phytium_i3c_master *master, - u32 ibir) -{ - struct phytium_i3c_i2c_dev_data *data; - bool data_consumed = false; - struct i3c_ibi_slot *slot; - u32 id = IBIR_SLVID(ibir); - struct i3c_dev_desc *dev; - size_t nbytes; - u8 *buf; - - /* - * FIXME: maybe we should report the FIFO OVF errors to the upper - * layer. - */ - if (id >= master->ibi.num_slots || (ibir & IBIR_ERROR)) - goto out; - - dev = master->ibi.slots[id]; - spin_lock(&master->ibi.lock); - - data = i3c_dev_get_master_data(dev); - slot = i3c_generic_ibi_get_free_slot(data->ibi_pool); - if (!slot) - goto out_unlock; - - buf = slot->data; - - nbytes = IBIR_XFER_BYTES(ibir); - readsl(master->regs + IBI_DATA_FIFO, buf, nbytes / 4); - if (nbytes % 3) { - u32 tmp = __raw_readl(master->regs + IBI_DATA_FIFO); - - memcpy(buf + (nbytes & ~3), &tmp, nbytes & 3); - } - - slot->len = min_t(unsigned int, IBIR_XFER_BYTES(ibir), - dev->ibi->max_payload_len); - i3c_master_queue_ibi(dev, slot); - data_consumed = true; - -out_unlock: - spin_unlock(&master->ibi.lock); - -out: - /* Consume data from the FIFO if it's not been done already. */ - if (!data_consumed) { - int i; - - for (i = 0; i < IBIR_XFER_BYTES(ibir); i += 4) - readl(master->regs + IBI_DATA_FIFO); - } -} - -static void phytium_i3c_master_demux_ibis(struct phytium_i3c_master *master) -{ - u32 status0; - - writel(MST_INT_IBIR_THR, master->regs + MST_ICR); - - for (status0 = readl(master->regs + MST_STATUS0); - !(status0 & MST_STATUS0_IBIR_EMP); - status0 = readl(master->regs + MST_STATUS0)) { - u32 ibir = readl(master->regs + IBIR); - - switch (IBIR_TYPE(ibir)) { - case IBIR_TYPE_IBI: - phytium_i3c_master_handle_ibi(master, ibir); - break; - - case IBIR_TYPE_HJ: - WARN_ON(IBIR_XFER_BYTES(ibir) || (ibir & IBIR_ERROR)); - queue_work(master->base.wq, &master->hj_work); - break; - - case IBIR_TYPE_MR: - WARN_ON(IBIR_XFER_BYTES(ibir) || (ibir & IBIR_ERROR)); - break; - default: - break; - } - } -} - -static irqreturn_t phytium_i3c_master_interrupt(int irq, void *data) -{ - struct phytium_i3c_master *master = data; - u32 status; - - status = readl(master->regs + MST_ISR); - if (!(status & readl(master->regs + MST_IMR))) - return IRQ_NONE; - - spin_lock(&master->xferqueue.lock); - phytium_i3c_master_end_xfer_locked(master, status); - spin_unlock(&master->xferqueue.lock); - - if (status & MST_INT_IBIR_THR) - phytium_i3c_master_demux_ibis(master); - - return IRQ_HANDLED; -} - -static int phytium_i3c_master_disable_ibi(struct i3c_dev_desc *dev) -{ - struct i3c_master_controller *m = i3c_dev_get_master(dev); - struct phytium_i3c_master *master = to_phytium_i3c_master(m); - struct phytium_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); - unsigned long flags; - u32 sirmap; - int ret; - - ret = i3c_master_disec_locked(m, dev->info.dyn_addr, - I3C_CCC_EVENT_SIR); - if (ret) - return ret; - - spin_lock_irqsave(&master->ibi.lock, flags); - sirmap = readl(master->regs + SIR_MAP_DEV_REG(data->ibi)); - sirmap &= ~SIR_MAP_DEV_CONF_MASK(data->ibi); - sirmap |= SIR_MAP_DEV_CONF(data->ibi, - SIR_MAP_DEV_DA(I3C_BROADCAST_ADDR)); - writel(sirmap, master->regs + SIR_MAP_DEV_REG(data->ibi)); - spin_unlock_irqrestore(&master->ibi.lock, flags); - - return ret; -} - -static int phytium_i3c_master_enable_ibi(struct i3c_dev_desc *dev) -{ - struct i3c_master_controller *m = i3c_dev_get_master(dev); - struct phytium_i3c_master *master = to_phytium_i3c_master(m); - struct phytium_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); - unsigned long flags; - u32 sircfg, sirmap; - int ret; - - spin_lock_irqsave(&master->ibi.lock, flags); - sirmap = readl(master->regs + SIR_MAP_DEV_REG(data->ibi)); - sirmap &= ~SIR_MAP_DEV_CONF_MASK(data->ibi); - sircfg = SIR_MAP_DEV_ROLE(dev->info.bcr >> 6) | - SIR_MAP_DEV_DA(dev->info.dyn_addr) | - SIR_MAP_DEV_PL(dev->info.max_ibi_len) | - SIR_MAP_DEV_ACK; - - if (dev->info.bcr & I3C_BCR_MAX_DATA_SPEED_LIM) - sircfg |= SIR_MAP_DEV_SLOW; - - sirmap |= SIR_MAP_DEV_CONF(data->ibi, sircfg); - writel(sirmap, master->regs + SIR_MAP_DEV_REG(data->ibi)); - spin_unlock_irqrestore(&master->ibi.lock, flags); - - ret = i3c_master_enec_locked(m, dev->info.dyn_addr, - I3C_CCC_EVENT_SIR); - if (ret) { - spin_lock_irqsave(&master->ibi.lock, flags); - sirmap = readl(master->regs + SIR_MAP_DEV_REG(data->ibi)); - sirmap &= ~SIR_MAP_DEV_CONF_MASK(data->ibi); - sirmap |= SIR_MAP_DEV_CONF(data->ibi, - SIR_MAP_DEV_DA(I3C_BROADCAST_ADDR)); - writel(sirmap, master->regs + SIR_MAP_DEV_REG(data->ibi)); - spin_unlock_irqrestore(&master->ibi.lock, flags); - } - - return ret; -} - -static int phytium_i3c_master_request_ibi(struct i3c_dev_desc *dev, - const struct i3c_ibi_setup *req) -{ - struct i3c_master_controller *m = i3c_dev_get_master(dev); - struct phytium_i3c_master *master = to_phytium_i3c_master(m); - struct phytium_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); - unsigned long flags; - unsigned int i; - - data->ibi_pool = i3c_generic_ibi_alloc_pool(dev, req); - if (IS_ERR(data->ibi_pool)) - return PTR_ERR(data->ibi_pool); - - spin_lock_irqsave(&master->ibi.lock, flags); - for (i = 0; i < master->ibi.num_slots; i++) { - if (!master->ibi.slots[i]) { - data->ibi = i; - master->ibi.slots[i] = dev; - break; - } - } - spin_unlock_irqrestore(&master->ibi.lock, flags); - - if (i < master->ibi.num_slots) - return 0; - - i3c_generic_ibi_free_pool(data->ibi_pool); - data->ibi_pool = NULL; - - return -ENOSPC; -} - -static void phytium_i3c_master_free_ibi(struct i3c_dev_desc *dev) -{ - struct i3c_master_controller *m = i3c_dev_get_master(dev); - struct phytium_i3c_master *master = to_phytium_i3c_master(m); - struct phytium_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); - unsigned long flags; - - spin_lock_irqsave(&master->ibi.lock, flags); - master->ibi.slots[data->ibi] = NULL; - data->ibi = -1; - spin_unlock_irqrestore(&master->ibi.lock, flags); - - i3c_generic_ibi_free_pool(data->ibi_pool); -} - -static void phytium_i3c_master_recycle_ibi_slot(struct i3c_dev_desc *dev, - struct i3c_ibi_slot *slot) -{ - struct phytium_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); - - i3c_generic_ibi_recycle_slot(data->ibi_pool, slot); -} - -static const struct i3c_master_controller_ops phytium_i3c_master_ops = { - .bus_init = phytium_i3c_master_bus_init, - .bus_cleanup = phytium_i3c_master_bus_cleanup, - .do_daa = phytium_i3c_master_do_daa, - .attach_i3c_dev = phytium_i3c_master_attach_i3c_dev, - .reattach_i3c_dev = phytium_i3c_master_reattach_i3c_dev, - .detach_i3c_dev = phytium_i3c_master_detach_i3c_dev, - .attach_i2c_dev = phytium_i3c_master_attach_i2c_dev, - .detach_i2c_dev = phytium_i3c_master_detach_i2c_dev, - .supports_ccc_cmd = phytium_i3c_master_supports_ccc_cmd, - .send_ccc_cmd = phytium_i3c_master_send_ccc_cmd, - .priv_xfers = phytium_i3c_master_priv_xfers, - .i2c_xfers = phytium_i3c_master_i2c_xfers, - .enable_ibi = phytium_i3c_master_enable_ibi, - .disable_ibi = phytium_i3c_master_disable_ibi, - .request_ibi = phytium_i3c_master_request_ibi, - .free_ibi = phytium_i3c_master_free_ibi, - .recycle_ibi_slot = phytium_i3c_master_recycle_ibi_slot, -}; - -static void phytium_i3c_master_hj(struct work_struct *work) -{ - struct phytium_i3c_master *master = container_of(work, - struct phytium_i3c_master, - hj_work); - - i3c_master_do_daa(&master->base); -} - -static struct phytium_i3c_data phytium_i3c_devdata = { - .thd_delay_ns = 10, -}; - -static const struct of_device_id phytium_i3c_master_of_ids[] = { - { .compatible = "phytium,cdns-i3c-master", .data = &phytium_i3c_devdata }, - { /* sentinel */ }, -}; - -static int phytium_i3c_master_probe(struct platform_device *pdev) -{ - struct phytium_i3c_master *master; - struct resource *res; - int ret, irq; - u32 val; - - master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL); - if (!master) - return -ENOMEM; - - master->devdata = of_device_get_match_data(&pdev->dev); - if (!master->devdata) - return -EINVAL; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - master->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(master->regs)) - return PTR_ERR(master->regs); - - master->pclk = devm_clk_get(&pdev->dev, "pclk"); - if (IS_ERR(master->pclk)) - return PTR_ERR(master->pclk); - - master->sysclk = devm_clk_get(&pdev->dev, "sysclk"); - if (IS_ERR(master->sysclk)) - return PTR_ERR(master->sysclk); - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - ret = clk_prepare_enable(master->pclk); - if (ret) - return ret; - - ret = clk_prepare_enable(master->sysclk); - if (ret) - goto err_disable_pclk; - - if (readl(master->regs + DEV_ID) != DEV_ID_I3C_MASTER) { - ret = -EINVAL; - goto err_disable_sysclk; - } - - spin_lock_init(&master->xferqueue.lock); - INIT_LIST_HEAD(&master->xferqueue.list); - - INIT_WORK(&master->hj_work, phytium_i3c_master_hj); - writel(0xffffffff, master->regs + MST_IDR); - writel(0xffffffff, master->regs + SLV_IDR); - ret = devm_request_irq(&pdev->dev, irq, phytium_i3c_master_interrupt, 0, - dev_name(&pdev->dev), master); - if (ret) - goto err_disable_sysclk; - - platform_set_drvdata(pdev, master); - - val = readl(master->regs + CONF_STATUS0); - - /* Device ID0 is reserved to describe this master. */ - master->maxdevs = CONF_STATUS0_DEVS_NUM(val); - master->free_rr_slots = GENMASK(master->maxdevs, 1); - - val = readl(master->regs + CONF_STATUS1); - master->caps.cmdfifodepth = CONF_STATUS1_CMD_DEPTH(val); - master->caps.rxfifodepth = CONF_STATUS1_RX_DEPTH(val); - master->caps.txfifodepth = CONF_STATUS1_TX_DEPTH(val); - master->caps.ibirfifodepth = CONF_STATUS0_IBIR_DEPTH(val); - master->caps.cmdrfifodepth = CONF_STATUS0_CMDR_DEPTH(val); - - spin_lock_init(&master->ibi.lock); - master->ibi.num_slots = CONF_STATUS1_IBI_HW_RES(val); - master->ibi.slots = devm_kcalloc(&pdev->dev, master->ibi.num_slots, - sizeof(*master->ibi.slots), - GFP_KERNEL); - if (!master->ibi.slots) { - ret = -ENOMEM; - goto err_disable_sysclk; - } - - writel(IBIR_THR(1), master->regs + CMD_IBI_THR_CTRL); - writel(MST_INT_IBIR_THR, master->regs + MST_IER); - writel(DEVS_CTRL_DEV_CLR_ALL, master->regs + DEVS_CTRL); - - ret = i3c_master_register(&master->base, &pdev->dev, - &phytium_i3c_master_ops, false); - if (ret) - goto err_disable_sysclk; - writel(readl(master->regs + CTRL) | CTRL_HJ_ACK, master->regs + CTRL); - return 0; - -err_disable_sysclk: - clk_disable_unprepare(master->sysclk); - -err_disable_pclk: - clk_disable_unprepare(master->pclk); - - return ret; -} - -static int phytium_i3c_master_remove(struct platform_device *pdev) -{ - struct phytium_i3c_master *master = platform_get_drvdata(pdev); - - i3c_master_unregister(&master->base); - - clk_disable_unprepare(master->sysclk); - clk_disable_unprepare(master->pclk); - - return 0; -} - -static struct platform_driver phytium_i3c_master = { - .probe = phytium_i3c_master_probe, - .remove = phytium_i3c_master_remove, - .driver = { - .name = "phytium-i3c-master", - .of_match_table = phytium_i3c_master_of_ids, - }, -}; -module_platform_driver(phytium_i3c_master); - -MODULE_AUTHOR("Feng Jun "); -MODULE_DESCRIPTION("Phytium I3C master driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:phytium-i3c-master"); From 878d2f927172ce2d46d40636639bbda4429df6d9 Mon Sep 17 00:00:00 2001 From: Avenger-285714 Date: Thu, 30 May 2024 11:55:07 +0800 Subject: [PATCH 4/8] Revert "dt-bindings: Add bindings for Phytium I3C controller" This reverts commit 106b9d2a81169a04fee389c8461b587984c08747. --- .../bindings/i3c/phytium,i3c-master.yaml | 35 ------------------- 1 file changed, 35 deletions(-) delete mode 100644 Documentation/devicetree/bindings/i3c/phytium,i3c-master.yaml diff --git a/Documentation/devicetree/bindings/i3c/phytium,i3c-master.yaml b/Documentation/devicetree/bindings/i3c/phytium,i3c-master.yaml deleted file mode 100644 index 0e004735fd38d..0000000000000 --- a/Documentation/devicetree/bindings/i3c/phytium,i3c-master.yaml +++ /dev/null @@ -1,35 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause - -* Phytium I3C controller - -This I3C controller is for Phytium Soc. - -Required properties: -- compatible: Shall be "phytium,cdns-i3c-master" -- clocks: Shall reference the pclk and sysclk -- clock-names: Shall contain "pclk" and "sysclk" -- interrupts: The interrupt line connected to this I3C master -- reg: I3C master registers -- #address-cells: Shall be set to 1 -- #size-cells: Shall be set to 0 -- i2c-scl-hz: I2C CLK frequency -- i3c-scl-hz: I3C CLK frequency - -Example: - - i3c-master@28045000 { - compatible = "phytium,cdns-i3c-master"; - reg = <0x0 0x28045000 0x0 0x1000>; - interrupts = ; - clocks = <&coreclock>, <&i3csysclock>; - clock-names = "pclk", "sysclk"; - #address-cells = <1>; - #size-cells = <0>; - i2c-scl-hz = <400000>; - i3c-scl-hz = <1000000>; - - nunchuk: nunchuk@52 { - compatible = "nintendo,nunchuk"; - reg = <0x52 0x0 0x10>; - }; - }; From d809c8a9f5ae39572e1ff0c02083b2cdb6f6b170 Mon Sep 17 00:00:00 2001 From: Avenger-285714 Date: Thu, 30 May 2024 11:55:07 +0800 Subject: [PATCH 5/8] Revert "arm64: i3c: cdns: phytium: Fix DAA fail at high frequency" This reverts commit 889c101c4ec75a3b5cbffcf230a0be82076c31ec. --- drivers/i3c/master/i3c-master-cdns.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c index 925deb7468b83..6fa0727e5ad97 100644 --- a/drivers/i3c/master/i3c-master-cdns.c +++ b/drivers/i3c/master/i3c-master-cdns.c @@ -1300,7 +1300,7 @@ static int cdns_i3c_master_bus_init(struct i3c_master_controller *m) * We will issue ENTDAA afterwards from the threaded IRQ handler. */ if (master->devdata->halt_disable) - ctrl |= CTRL_HJ_DISEC | CTRL_MCS_EN; + ctrl |= CTRL_HJ_ACK | CTRL_HJ_DISEC | CTRL_MCS_EN; else ctrl |= CTRL_HJ_ACK | CTRL_HJ_DISEC | CTRL_HALT_EN | CTRL_MCS_EN; @@ -1675,8 +1675,6 @@ static int cdns_i3c_master_probe(struct platform_device *pdev) if (ret) goto err_disable_sysclk; - writel(readl(master->regs + CTRL) | CTRL_HJ_ACK, master->regs + CTRL); - return 0; err_disable_sysclk: From 2e3f87b99d5c3c4de2d63af849f20c7b561bc7f8 Mon Sep 17 00:00:00 2001 From: Avenger-285714 Date: Thu, 30 May 2024 11:55:07 +0800 Subject: [PATCH 6/8] Revert "arm64: i3c: cdns: phytium: Add GETMXDS format 1 retransmission" This reverts commit 8df2c2846359e7fc851ff1cadffd6996e1a44c11. --- drivers/i3c/master/i3c-master-cdns.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c index 6fa0727e5ad97..2718460dfb891 100644 --- a/drivers/i3c/master/i3c-master-cdns.c +++ b/drivers/i3c/master/i3c-master-cdns.c @@ -725,19 +725,6 @@ static int cdns_i3c_master_send_ccc_cmd(struct i3c_master_controller *m, if (!wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000))) cdns_i3c_master_unqueue_xfer(master, xfer); - /*GETMXDS format 1 need retransmission*/ - if ((xfer->ret) && (cmd->id == I3C_CCC_GETMXDS)) { - if (cmd->dests[0].payload.len == 5) { - cmd->dests[0].payload.len = 2; - ccmd->rx_len = cmd->dests[0].payload.len; - ccmd->cmd0 &= 0xfff000fff; - ccmd->cmd0 |= CMD0_FIFO_PL_LEN(cmd->dests[0].payload.len); - cdns_i3c_master_queue_xfer(master, xfer); - if (!wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000))) - cdns_i3c_master_unqueue_xfer(master, xfer); - } - } - ret = xfer->ret; cmd->err = cdns_i3c_cmd_get_err(&xfer->cmds[0]); cdns_i3c_master_free_xfer(xfer); From 5486a550e79f7d9eef36ab3132b46c65ccab625d Mon Sep 17 00:00:00 2001 From: Avenger-285714 Date: Thu, 30 May 2024 11:55:07 +0800 Subject: [PATCH 7/8] Revert "arm64: i3c: cdns: add support for Phytium workaround" This reverts commit 8153a1cadae89c8cedc6c269631462f9629e3ec4. --- drivers/i3c/master/i3c-master-cdns.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c index 2718460dfb891..fa5aaaf446181 100644 --- a/drivers/i3c/master/i3c-master-cdns.c +++ b/drivers/i3c/master/i3c-master-cdns.c @@ -393,7 +393,6 @@ struct cdns_i3c_xfer { struct cdns_i3c_data { u8 thd_delay_ns; - u8 halt_disable; }; struct cdns_i3c_master { @@ -1286,10 +1285,7 @@ static int cdns_i3c_master_bus_init(struct i3c_master_controller *m) * * We will issue ENTDAA afterwards from the threaded IRQ handler. */ - if (master->devdata->halt_disable) - ctrl |= CTRL_HJ_ACK | CTRL_HJ_DISEC | CTRL_MCS_EN; - else - ctrl |= CTRL_HJ_ACK | CTRL_HJ_DISEC | CTRL_HALT_EN | CTRL_MCS_EN; + ctrl |= CTRL_HJ_ACK | CTRL_HJ_DISEC | CTRL_HALT_EN | CTRL_MCS_EN; /* * Configure data hold delay based on device-specific data. @@ -1560,17 +1556,10 @@ static void cdns_i3c_master_hj(struct work_struct *work) static struct cdns_i3c_data cdns_i3c_devdata = { .thd_delay_ns = 10, - .halt_disable = 0, -}; - -static struct cdns_i3c_data phytium_i3c_devdata = { - .thd_delay_ns = 10, - .halt_disable = 1, }; static const struct of_device_id cdns_i3c_master_of_ids[] = { { .compatible = "cdns,i3c-master", .data = &cdns_i3c_devdata }, - { .compatible = "phytium,cdns-i3c-master", .data = &phytium_i3c_devdata}, { /* sentinel */ }, }; From eb6e995789383eec0969a1d3656975d699078c54 Mon Sep 17 00:00:00 2001 From: Avenger-285714 Date: Thu, 30 May 2024 11:55:07 +0800 Subject: [PATCH 8/8] Revert "dt-bindings: i3c: cdns: Add compatible string for Phytium SoCs" This reverts commit b1bc2dbfeb91f3d712f91d3568aa58ba5176e3d2. --- Documentation/devicetree/bindings/i3c/cdns,i3c-master.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/i3c/cdns,i3c-master.yaml b/Documentation/devicetree/bindings/i3c/cdns,i3c-master.yaml index ebc572300e3b7..cc40d25358ecf 100644 --- a/Documentation/devicetree/bindings/i3c/cdns,i3c-master.yaml +++ b/Documentation/devicetree/bindings/i3c/cdns,i3c-master.yaml @@ -14,9 +14,7 @@ allOf: properties: compatible: - enum: - - cdns,i3c-master - - phytium,cdns-i3c-master + const: cdns,i3c-master reg: maxItems: 1