Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'i3c/for-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux

Pull i3c updates from Alexandre Belloni:
"Subsystem:
- OF alias bus numbering
- convert to platform remove callback returning void

New driver:
- AST2600 controller, based on Synopsys DesignWare IP

Driver update:
- dw: add infrastructure to support different platform integrations"

* tag 'i3c/for-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux:
i3c: ast2600: set variable ast2600_i3c_ops storage-class-specifier to static
i3c: ast2600: fix register setting for 545 ohm pullups
i3c: ast2600: enable IBI support
i3c: dw: Add a platform facility for IBI PEC workarounds
i3c: dw: Add support for in-band interrupts
i3c: dw: Turn DAT array entry into a struct
i3c: dw: Create a generic fifo read function
i3c: Allow OF-alias-based persistent bus numbering
i3c: ast2600: Add AST2600 platform-specific driver
dt-bindings: i3c: Add AST2600 i3c controller
i3c: dw: Add infrastructure for platform-specific implementations
i3c: dw: use bus mode rather than device reg for conditional tCAS setting
i3c: dw: Return the length from a read priv_xfer
i3c: svc: Convert to platform remove callback returning void
i3c: mipi-i3c-hci: Convert to platform remove callback returning void
i3c: cdns: Convert to platform remove callback returning void
i3c: dw: Convert to platform remove callback returning void
i3c: Make i3c_master_unregister() return void
i3c: dw: drop of_match_ptr for ID table
i3c: Correct reference to the I²C device data type

+779 -91
+72
Documentation/devicetree/bindings/i3c/aspeed,ast2600-i3c.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/i3c/aspeed,ast2600-i3c.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: ASPEED AST2600 i3c controller 8 + 9 + maintainers: 10 + - Jeremy Kerr <jk@codeconstruct.com.au> 11 + 12 + allOf: 13 + - $ref: i3c.yaml# 14 + 15 + properties: 16 + compatible: 17 + const: aspeed,ast2600-i3c 18 + 19 + reg: 20 + maxItems: 1 21 + 22 + clocks: 23 + maxItems: 1 24 + 25 + resets: 26 + maxItems: 1 27 + 28 + interrupts: 29 + maxItems: 1 30 + 31 + sda-pullup-ohms: 32 + enum: [545, 750, 2000] 33 + default: 2000 34 + description: | 35 + Value to configure SDA pullup resistor, in Ohms. 36 + 37 + aspeed,global-regs: 38 + $ref: /schemas/types.yaml#/definitions/phandle-array 39 + items: 40 + - items: 41 + - description: phandle to i3c global register syscon node 42 + - description: index of this i3c controller in the global register set 43 + description: | 44 + A (phandle, controller index) reference to the i3c global register set 45 + used for this device. 46 + 47 + required: 48 + - compatible 49 + - reg 50 + - clocks 51 + - interrupts 52 + - aspeed,global-regs 53 + 54 + unevaluatedProperties: false 55 + 56 + examples: 57 + - | 58 + #include <dt-bindings/interrupt-controller/arm-gic.h> 59 + 60 + i3c-master@2000 { 61 + compatible = "aspeed,ast2600-i3c"; 62 + reg = <0x2000 0x1000>; 63 + #address-cells = <3>; 64 + #size-cells = <0>; 65 + clocks = <&syscon 0>; 66 + resets = <&syscon 0>; 67 + aspeed,global-regs = <&i3c_global 0>; 68 + pinctrl-names = "default"; 69 + pinctrl-0 = <&pinctrl_i3c1_default>; 70 + interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>; 71 + }; 72 + ...
+6
MAINTAINERS
··· 9778 9778 F: Documentation/devicetree/bindings/i3c/snps,dw-i3c-master.yaml 9779 9779 F: drivers/i3c/master/dw* 9780 9780 9781 + I3C DRIVER FOR ASPEED AST2600 9782 + M: Jeremy Kerr <jk@codeconstruct.com.au> 9783 + S: Maintained 9784 + F: Documentation/devicetree/bindings/i3c/aspeed,ast2600-i3c.yaml 9785 + F: drivers/i3c/master/ast2600-i3c-master.c 9786 + 9781 9787 I3C SUBSYSTEM 9782 9788 M: Alexandre Belloni <alexandre.belloni@bootlin.com> 9783 9789 L: linux-i3c@lists.infradead.org (moderated for non-subscribers)
+26 -10
drivers/i3c/master.c
··· 21 21 22 22 static DEFINE_IDR(i3c_bus_idr); 23 23 static DEFINE_MUTEX(i3c_core_lock); 24 + static int __i3c_first_dynamic_bus_num; 24 25 25 26 /** 26 27 * i3c_bus_maintenance_lock - Lock the bus for a maintenance operation ··· 420 419 mutex_unlock(&i3c_core_lock); 421 420 } 422 421 423 - static int i3c_bus_init(struct i3c_bus *i3cbus) 422 + static int i3c_bus_init(struct i3c_bus *i3cbus, struct device_node *np) 424 423 { 425 - int ret; 424 + int ret, start, end, id = -1; 426 425 427 426 init_rwsem(&i3cbus->lock); 428 427 INIT_LIST_HEAD(&i3cbus->devs.i2c); ··· 430 429 i3c_bus_init_addrslots(i3cbus); 431 430 i3cbus->mode = I3C_BUS_MODE_PURE; 432 431 432 + if (np) 433 + id = of_alias_get_id(np, "i3c"); 434 + 433 435 mutex_lock(&i3c_core_lock); 434 - ret = idr_alloc(&i3c_bus_idr, i3cbus, 0, 0, GFP_KERNEL); 436 + if (id >= 0) { 437 + start = id; 438 + end = start + 1; 439 + } else { 440 + start = __i3c_first_dynamic_bus_num; 441 + end = 0; 442 + } 443 + 444 + ret = idr_alloc(&i3c_bus_idr, i3cbus, start, end, GFP_KERNEL); 435 445 mutex_unlock(&i3c_core_lock); 436 446 437 447 if (ret < 0) ··· 2618 2606 INIT_LIST_HEAD(&master->boardinfo.i2c); 2619 2607 INIT_LIST_HEAD(&master->boardinfo.i3c); 2620 2608 2621 - ret = i3c_bus_init(i3cbus); 2609 + ret = i3c_bus_init(i3cbus, master->dev.of_node); 2622 2610 if (ret) 2623 2611 return ret; 2624 2612 ··· 2707 2695 * @master: master used to send frames on the bus 2708 2696 * 2709 2697 * Basically undo everything done in i3c_master_register(). 2710 - * 2711 - * Return: 0 in case of success, a negative error code otherwise. 2712 2698 */ 2713 - int i3c_master_unregister(struct i3c_master_controller *master) 2699 + void i3c_master_unregister(struct i3c_master_controller *master) 2714 2700 { 2715 2701 i3c_master_i2c_adapter_cleanup(master); 2716 2702 i3c_master_unregister_i3c_devs(master); 2717 2703 i3c_master_bus_cleanup(master); 2718 2704 device_unregister(&master->dev); 2719 - 2720 - return 0; 2721 2705 } 2722 2706 EXPORT_SYMBOL_GPL(i3c_master_unregister); 2723 2707 ··· 2842 2834 2843 2835 static int __init i3c_init(void) 2844 2836 { 2845 - int res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier); 2837 + int res; 2846 2838 2839 + res = of_alias_get_highest_id("i3c"); 2840 + if (res >= 0) { 2841 + mutex_lock(&i3c_core_lock); 2842 + __i3c_first_dynamic_bus_num = res + 1; 2843 + mutex_unlock(&i3c_core_lock); 2844 + } 2845 + 2846 + res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier); 2847 2847 if (res) 2848 2848 return res; 2849 2849
+14
drivers/i3c/master/Kconfig
··· 22 22 This driver can also be built as a module. If so, the module 23 23 will be called dw-i3c-master. 24 24 25 + config AST2600_I3C_MASTER 26 + tristate "ASPEED AST2600 I3C master driver" 27 + depends on DW_I3C_MASTER 28 + depends on ARCH_ASPEED || COMPILE_TEST 29 + select MFD_SYSCON 30 + help 31 + Support for ASPEED AST2600 I3C Controller. 32 + 33 + This hardware is an instance of the DW I3C controller; this 34 + driver adds platform- specific support for AST2600 hardware. 35 + 36 + This driver can also be built as a module. If so, the module 37 + will be called ast2600-i3c-master. 38 + 25 39 config SVC_I3C_MASTER 26 40 tristate "Silvaco I3C Dual-Role Master driver" 27 41 depends on I3C
+1
drivers/i3c/master/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 obj-$(CONFIG_CDNS_I3C_MASTER) += i3c-master-cdns.o 3 3 obj-$(CONFIG_DW_I3C_MASTER) += dw-i3c-master.o 4 + obj-$(CONFIG_AST2600_I3C_MASTER) += ast2600-i3c-master.o 4 5 obj-$(CONFIG_SVC_I3C_MASTER) += svc-i3c-master.o 5 6 obj-$(CONFIG_MIPI_I3C_HCI) += mipi-i3c-hci/
+189
drivers/i3c/master/ast2600-i3c-master.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2023 Code Construct 4 + * 5 + * Author: Jeremy Kerr <jk@codeconstruct.com.au> 6 + */ 7 + 8 + #include <linux/mfd/syscon.h> 9 + #include <linux/module.h> 10 + #include <linux/of.h> 11 + #include <linux/of_device.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/regmap.h> 14 + 15 + #include "dw-i3c-master.h" 16 + 17 + /* AST2600-specific global register set */ 18 + #define AST2600_I3CG_REG0(idx) (((idx) * 4 * 4) + 0x10) 19 + #define AST2600_I3CG_REG1(idx) (((idx) * 4 * 4) + 0x14) 20 + 21 + #define AST2600_I3CG_REG0_SDA_PULLUP_EN_MASK GENMASK(29, 28) 22 + #define AST2600_I3CG_REG0_SDA_PULLUP_EN_2K (0x0 << 28) 23 + #define AST2600_I3CG_REG0_SDA_PULLUP_EN_750 (0x2 << 28) 24 + #define AST2600_I3CG_REG0_SDA_PULLUP_EN_545 (0x3 << 28) 25 + 26 + #define AST2600_I3CG_REG1_I2C_MODE BIT(0) 27 + #define AST2600_I3CG_REG1_TEST_MODE BIT(1) 28 + #define AST2600_I3CG_REG1_ACT_MODE_MASK GENMASK(3, 2) 29 + #define AST2600_I3CG_REG1_ACT_MODE(x) (((x) << 2) & AST2600_I3CG_REG1_ACT_MODE_MASK) 30 + #define AST2600_I3CG_REG1_PENDING_INT_MASK GENMASK(7, 4) 31 + #define AST2600_I3CG_REG1_PENDING_INT(x) (((x) << 4) & AST2600_I3CG_REG1_PENDING_INT_MASK) 32 + #define AST2600_I3CG_REG1_SA_MASK GENMASK(14, 8) 33 + #define AST2600_I3CG_REG1_SA(x) (((x) << 8) & AST2600_I3CG_REG1_SA_MASK) 34 + #define AST2600_I3CG_REG1_SA_EN BIT(15) 35 + #define AST2600_I3CG_REG1_INST_ID_MASK GENMASK(19, 16) 36 + #define AST2600_I3CG_REG1_INST_ID(x) (((x) << 16) & AST2600_I3CG_REG1_INST_ID_MASK) 37 + 38 + #define AST2600_DEFAULT_SDA_PULLUP_OHMS 2000 39 + 40 + #define DEV_ADDR_TABLE_IBI_PEC BIT(11) 41 + 42 + struct ast2600_i3c { 43 + struct dw_i3c_master dw; 44 + struct regmap *global_regs; 45 + unsigned int global_idx; 46 + unsigned int sda_pullup; 47 + }; 48 + 49 + static struct ast2600_i3c *to_ast2600_i3c(struct dw_i3c_master *dw) 50 + { 51 + return container_of(dw, struct ast2600_i3c, dw); 52 + } 53 + 54 + static int ast2600_i3c_pullup_to_reg(unsigned int ohms, u32 *regp) 55 + { 56 + u32 reg; 57 + 58 + switch (ohms) { 59 + case 2000: 60 + reg = AST2600_I3CG_REG0_SDA_PULLUP_EN_2K; 61 + break; 62 + case 750: 63 + reg = AST2600_I3CG_REG0_SDA_PULLUP_EN_750; 64 + break; 65 + case 545: 66 + reg = AST2600_I3CG_REG0_SDA_PULLUP_EN_545; 67 + break; 68 + default: 69 + return -EINVAL; 70 + } 71 + 72 + if (regp) 73 + *regp = reg; 74 + 75 + return 0; 76 + } 77 + 78 + static int ast2600_i3c_init(struct dw_i3c_master *dw) 79 + { 80 + struct ast2600_i3c *i3c = to_ast2600_i3c(dw); 81 + u32 reg = 0; 82 + int rc; 83 + 84 + /* reg0: set SDA pullup values */ 85 + rc = ast2600_i3c_pullup_to_reg(i3c->sda_pullup, &reg); 86 + if (rc) 87 + return rc; 88 + 89 + rc = regmap_write(i3c->global_regs, 90 + AST2600_I3CG_REG0(i3c->global_idx), reg); 91 + if (rc) 92 + return rc; 93 + 94 + /* reg1: set up the instance id, but leave everything else disabled, 95 + * as it's all for client mode 96 + */ 97 + reg = AST2600_I3CG_REG1_INST_ID(i3c->global_idx); 98 + rc = regmap_write(i3c->global_regs, 99 + AST2600_I3CG_REG1(i3c->global_idx), reg); 100 + 101 + return rc; 102 + } 103 + 104 + static void ast2600_i3c_set_dat_ibi(struct dw_i3c_master *i3c, 105 + struct i3c_dev_desc *dev, 106 + bool enable, u32 *dat) 107 + { 108 + /* 109 + * The ast2600 i3c controller will lock up on receiving 4n+1-byte IBIs 110 + * if the PEC is disabled. We have no way to restrict the length of 111 + * IBIs sent to the controller, so we need to unconditionally enable 112 + * PEC checking, which means we drop a byte of payload data 113 + */ 114 + if (enable && dev->info.bcr & I3C_BCR_IBI_PAYLOAD) { 115 + dev_warn_once(&i3c->base.dev, 116 + "Enabling PEC workaround. IBI payloads will be truncated\n"); 117 + *dat |= DEV_ADDR_TABLE_IBI_PEC; 118 + } 119 + } 120 + 121 + static const struct dw_i3c_platform_ops ast2600_i3c_ops = { 122 + .init = ast2600_i3c_init, 123 + .set_dat_ibi = ast2600_i3c_set_dat_ibi, 124 + }; 125 + 126 + static int ast2600_i3c_probe(struct platform_device *pdev) 127 + { 128 + struct device_node *np = pdev->dev.of_node; 129 + struct of_phandle_args gspec; 130 + struct ast2600_i3c *i3c; 131 + int rc; 132 + 133 + i3c = devm_kzalloc(&pdev->dev, sizeof(*i3c), GFP_KERNEL); 134 + if (!i3c) 135 + return -ENOMEM; 136 + 137 + rc = of_parse_phandle_with_fixed_args(np, "aspeed,global-regs", 1, 0, 138 + &gspec); 139 + if (rc) 140 + return -ENODEV; 141 + 142 + i3c->global_regs = syscon_node_to_regmap(gspec.np); 143 + of_node_put(gspec.np); 144 + 145 + if (IS_ERR(i3c->global_regs)) 146 + return PTR_ERR(i3c->global_regs); 147 + 148 + i3c->global_idx = gspec.args[0]; 149 + 150 + rc = of_property_read_u32(np, "sda-pullup-ohms", &i3c->sda_pullup); 151 + if (rc) 152 + i3c->sda_pullup = AST2600_DEFAULT_SDA_PULLUP_OHMS; 153 + 154 + rc = ast2600_i3c_pullup_to_reg(i3c->sda_pullup, NULL); 155 + if (rc) 156 + dev_err(&pdev->dev, "invalid sda-pullup value %d\n", 157 + i3c->sda_pullup); 158 + 159 + i3c->dw.platform_ops = &ast2600_i3c_ops; 160 + i3c->dw.ibi_capable = true; 161 + return dw_i3c_common_probe(&i3c->dw, pdev); 162 + } 163 + 164 + static void ast2600_i3c_remove(struct platform_device *pdev) 165 + { 166 + struct dw_i3c_master *dw_i3c = platform_get_drvdata(pdev); 167 + 168 + dw_i3c_common_remove(dw_i3c); 169 + } 170 + 171 + static const struct of_device_id ast2600_i3c_master_of_match[] = { 172 + { .compatible = "aspeed,ast2600-i3c", }, 173 + {}, 174 + }; 175 + MODULE_DEVICE_TABLE(of, ast2600_i3c_master_of_match); 176 + 177 + static struct platform_driver ast2600_i3c_driver = { 178 + .probe = ast2600_i3c_probe, 179 + .remove_new = ast2600_i3c_remove, 180 + .driver = { 181 + .name = "ast2600-i3c-master", 182 + .of_match_table = ast2600_i3c_master_of_match, 183 + }, 184 + }; 185 + module_platform_driver(ast2600_i3c_driver); 186 + 187 + MODULE_AUTHOR("Jeremy Kerr <jk@codeconstruct.com.au>"); 188 + MODULE_DESCRIPTION("ASPEED AST2600 I3C driver"); 189 + MODULE_LICENSE("GPL");
+375 -60
drivers/i3c/master/dw-i3c-master.c
··· 21 21 #include <linux/reset.h> 22 22 #include <linux/slab.h> 23 23 24 + #include "dw-i3c-master.h" 25 + 24 26 #define DEVICE_CTRL 0x0 25 27 #define DEV_CTRL_ENABLE BIT(31) 26 28 #define DEV_CTRL_RESUME BIT(30) ··· 76 74 77 75 #define RX_TX_DATA_PORT 0x14 78 76 #define IBI_QUEUE_STATUS 0x18 77 + #define IBI_QUEUE_STATUS_IBI_ID(x) (((x) & GENMASK(15, 8)) >> 8) 78 + #define IBI_QUEUE_STATUS_DATA_LEN(x) ((x) & GENMASK(7, 0)) 79 + #define IBI_QUEUE_IBI_ADDR(x) (IBI_QUEUE_STATUS_IBI_ID(x) >> 1) 80 + #define IBI_QUEUE_IBI_RNW(x) (IBI_QUEUE_STATUS_IBI_ID(x) & BIT(0)) 81 + #define IBI_TYPE_MR(x) \ 82 + ((IBI_QUEUE_IBI_ADDR(x) != I3C_HOT_JOIN_ADDR) && !IBI_QUEUE_IBI_RNW(x)) 83 + #define IBI_TYPE_HJ(x) \ 84 + ((IBI_QUEUE_IBI_ADDR(x) == I3C_HOT_JOIN_ADDR) && !IBI_QUEUE_IBI_RNW(x)) 85 + #define IBI_TYPE_SIRQ(x) \ 86 + ((IBI_QUEUE_IBI_ADDR(x) != I3C_HOT_JOIN_ADDR) && IBI_QUEUE_IBI_RNW(x)) 87 + 79 88 #define QUEUE_THLD_CTRL 0x1c 89 + #define QUEUE_THLD_CTRL_IBI_STAT_MASK GENMASK(31, 24) 90 + #define QUEUE_THLD_CTRL_IBI_STAT(x) (((x) - 1) << 24) 91 + #define QUEUE_THLD_CTRL_IBI_DATA_MASK GENMASK(20, 16) 92 + #define QUEUE_THLD_CTRL_IBI_DATA(x) ((x) << 16) 80 93 #define QUEUE_THLD_CTRL_RESP_BUF_MASK GENMASK(15, 8) 81 94 #define QUEUE_THLD_CTRL_RESP_BUF(x) (((x) - 1) << 8) 82 95 ··· 201 184 #define EXTENDED_CAPABILITY 0xe8 202 185 #define SLAVE_CONFIG 0xec 203 186 187 + #define DEV_ADDR_TABLE_IBI_MDB BIT(12) 188 + #define DEV_ADDR_TABLE_SIR_REJECT BIT(13) 204 189 #define DEV_ADDR_TABLE_LEGACY_I2C_DEV BIT(31) 205 190 #define DEV_ADDR_TABLE_DYNAMIC_ADDR(x) (((x) << 16) & GENMASK(23, 16)) 206 191 #define DEV_ADDR_TABLE_STATIC_ADDR(x) ((x) & GENMASK(6, 0)) 207 192 #define DEV_ADDR_TABLE_LOC(start, idx) ((start) + ((idx) << 2)) 208 - 209 - #define MAX_DEVS 32 210 193 211 194 #define I3C_BUS_SDR1_SCL_RATE 8000000 212 195 #define I3C_BUS_SDR2_SCL_RATE 6000000 ··· 217 200 #define I3C_BUS_THIGH_MAX_NS 41 218 201 219 202 #define XFER_TIMEOUT (msecs_to_jiffies(1000)) 220 - 221 - struct dw_i3c_master_caps { 222 - u8 cmdfifodepth; 223 - u8 datafifodepth; 224 - }; 225 203 226 204 struct dw_i3c_cmd { 227 205 u32 cmd_lo; ··· 236 224 struct dw_i3c_cmd cmds[]; 237 225 }; 238 226 239 - struct dw_i3c_master { 240 - struct i3c_master_controller base; 241 - u16 maxdevs; 242 - u16 datstartaddr; 243 - u32 free_pos; 244 - struct { 245 - struct list_head list; 246 - struct dw_i3c_xfer *cur; 247 - spinlock_t lock; 248 - } xferqueue; 249 - struct dw_i3c_master_caps caps; 250 - void __iomem *regs; 251 - struct reset_control *core_rst; 252 - struct clk *core_clk; 253 - char version[5]; 254 - char type[5]; 255 - u8 addrs[MAX_DEVS]; 256 - }; 257 - 258 227 struct dw_i3c_i2c_dev_data { 259 228 u8 index; 229 + struct i3c_generic_ibi_pool *ibi_pool; 260 230 }; 261 231 262 232 static u8 even_parity(u8 p) ··· 309 315 int pos; 310 316 311 317 for (pos = 0; pos < master->maxdevs; pos++) { 312 - if (addr == master->addrs[pos]) 318 + if (addr == master->devs[pos].addr) 313 319 return pos; 314 320 } 315 321 ··· 336 342 } 337 343 } 338 344 339 - static void dw_i3c_master_read_rx_fifo(struct dw_i3c_master *master, 340 - u8 *bytes, int nbytes) 345 + static void dw_i3c_master_read_fifo(struct dw_i3c_master *master, 346 + int reg, u8 *bytes, int nbytes) 341 347 { 342 - readsl(master->regs + RX_TX_DATA_PORT, bytes, nbytes / 4); 348 + readsl(master->regs + reg, bytes, nbytes / 4); 343 349 if (nbytes & 3) { 344 350 u32 tmp; 345 351 346 - readsl(master->regs + RX_TX_DATA_PORT, &tmp, 1); 352 + readsl(master->regs + reg, &tmp, 1); 347 353 memcpy(bytes + (nbytes & ~3), &tmp, nbytes & 3); 348 354 } 355 + } 356 + 357 + static void dw_i3c_master_read_rx_fifo(struct dw_i3c_master *master, 358 + u8 *bytes, int nbytes) 359 + { 360 + return dw_i3c_master_read_fifo(master, RX_TX_DATA_PORT, bytes, nbytes); 361 + } 362 + 363 + static void dw_i3c_master_read_ibi_fifo(struct dw_i3c_master *master, 364 + u8 *bytes, int nbytes) 365 + { 366 + return dw_i3c_master_read_fifo(master, IBI_QUEUE_STATUS, bytes, nbytes); 349 367 } 350 368 351 369 static struct dw_i3c_xfer * ··· 544 538 scl_timing = SCL_I3C_TIMING_HCNT(hcnt) | SCL_I3C_TIMING_LCNT(lcnt); 545 539 writel(scl_timing, master->regs + SCL_I3C_PP_TIMING); 546 540 547 - if (!(readl(master->regs + DEVICE_CTRL) & DEV_CTRL_I2C_SLAVE_PRESENT)) 541 + /* 542 + * In pure i3c mode, MST_FREE represents tCAS. In shared mode, this 543 + * will be set up by dw_i2c_clk_cfg as tLOW. 544 + */ 545 + if (master->base.bus.mode == I3C_BUS_MODE_PURE) 548 546 writel(BUS_I3C_MST_FREE(lcnt), master->regs + BUS_FREE_TIMING); 549 547 550 548 lcnt = max_t(u8, ··· 608 598 u32 thld_ctrl; 609 599 int ret; 610 600 601 + ret = master->platform_ops->init(master); 602 + if (ret) 603 + return ret; 604 + 611 605 switch (bus->mode) { 612 606 case I3C_BUS_MODE_MIXED_FAST: 613 607 case I3C_BUS_MODE_MIXED_LIMITED: ··· 629 615 } 630 616 631 617 thld_ctrl = readl(master->regs + QUEUE_THLD_CTRL); 632 - thld_ctrl &= ~QUEUE_THLD_CTRL_RESP_BUF_MASK; 618 + thld_ctrl &= ~(QUEUE_THLD_CTRL_RESP_BUF_MASK | 619 + QUEUE_THLD_CTRL_IBI_STAT_MASK | 620 + QUEUE_THLD_CTRL_IBI_STAT_MASK); 621 + thld_ctrl |= QUEUE_THLD_CTRL_IBI_STAT(1) | 622 + QUEUE_THLD_CTRL_IBI_DATA(31); 633 623 writel(thld_ctrl, master->regs + QUEUE_THLD_CTRL); 634 624 635 625 thld_ctrl = readl(master->regs + DATA_BUFFER_THLD_CTRL); ··· 797 779 if (ret < 0) 798 780 return -ENOSPC; 799 781 800 - master->addrs[pos] = ret; 782 + master->devs[pos].addr = ret; 801 783 p = even_parity(ret); 802 784 last_addr = ret; 803 785 ret |= (p << 7); ··· 834 816 835 817 for (pos = 0; pos < master->maxdevs; pos++) { 836 818 if (newdevs & BIT(pos)) 837 - i3c_master_add_i3c_dev_locked(m, master->addrs[pos]); 819 + i3c_master_add_i3c_dev_locked(m, master->devs[pos].addr); 838 820 } 839 821 840 822 dw_i3c_master_free_xfer(xfer); ··· 905 887 if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT)) 906 888 dw_i3c_master_dequeue_xfer(master, xfer); 907 889 890 + for (i = 0; i < i3c_nxfers; i++) { 891 + struct dw_i3c_cmd *cmd = &xfer->cmds[i]; 892 + 893 + if (i3c_xfers[i].rnw) 894 + i3c_xfers[i].len = cmd->rx_len; 895 + } 896 + 908 897 ret = xfer->ret; 909 898 dw_i3c_master_free_xfer(xfer); 910 899 ··· 933 908 master->regs + 934 909 DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); 935 910 936 - master->addrs[data->index] = 0; 911 + master->devs[data->index].addr = 0; 937 912 master->free_pos |= BIT(data->index); 938 913 939 914 data->index = pos; 940 - master->addrs[pos] = dev->info.dyn_addr; 915 + master->devs[pos].addr = dev->info.dyn_addr; 941 916 master->free_pos &= ~BIT(pos); 942 917 } 943 918 ··· 945 920 master->regs + 946 921 DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); 947 922 948 - master->addrs[data->index] = dev->info.dyn_addr; 923 + master->devs[data->index].addr = dev->info.dyn_addr; 949 924 950 925 return 0; 951 926 } ··· 966 941 return -ENOMEM; 967 942 968 943 data->index = pos; 969 - master->addrs[pos] = dev->info.dyn_addr ? : dev->info.static_addr; 944 + master->devs[pos].addr = dev->info.dyn_addr ? : dev->info.static_addr; 970 945 master->free_pos &= ~BIT(pos); 971 946 i3c_dev_set_master_data(dev, data); 972 947 973 - writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(master->addrs[pos]), 948 + writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(master->devs[pos].addr), 974 949 master->regs + 975 950 DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); 976 951 ··· 988 963 DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); 989 964 990 965 i3c_dev_set_master_data(dev, NULL); 991 - master->addrs[data->index] = 0; 966 + master->devs[data->index].addr = 0; 992 967 master->free_pos |= BIT(data->index); 993 968 kfree(data); 994 969 } ··· 1074 1049 return -ENOMEM; 1075 1050 1076 1051 data->index = pos; 1077 - master->addrs[pos] = dev->addr; 1052 + master->devs[pos].addr = dev->addr; 1078 1053 master->free_pos &= ~BIT(pos); 1079 1054 i2c_dev_set_master_data(dev, data); 1080 1055 ··· 1097 1072 DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); 1098 1073 1099 1074 i2c_dev_set_master_data(dev, NULL); 1100 - master->addrs[data->index] = 0; 1075 + master->devs[data->index].addr = 0; 1101 1076 master->free_pos |= BIT(data->index); 1102 1077 kfree(data); 1078 + } 1079 + 1080 + static int dw_i3c_master_request_ibi(struct i3c_dev_desc *dev, 1081 + const struct i3c_ibi_setup *req) 1082 + { 1083 + struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); 1084 + struct i3c_master_controller *m = i3c_dev_get_master(dev); 1085 + struct dw_i3c_master *master = to_dw_i3c_master(m); 1086 + unsigned long flags; 1087 + 1088 + data->ibi_pool = i3c_generic_ibi_alloc_pool(dev, req); 1089 + if (IS_ERR(data->ibi_pool)) 1090 + return PTR_ERR(data->ibi_pool); 1091 + 1092 + spin_lock_irqsave(&master->devs_lock, flags); 1093 + master->devs[data->index].ibi_dev = dev; 1094 + spin_unlock_irqrestore(&master->devs_lock, flags); 1095 + 1096 + return 0; 1097 + } 1098 + 1099 + static void dw_i3c_master_free_ibi(struct i3c_dev_desc *dev) 1100 + { 1101 + struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); 1102 + struct i3c_master_controller *m = i3c_dev_get_master(dev); 1103 + struct dw_i3c_master *master = to_dw_i3c_master(m); 1104 + unsigned long flags; 1105 + 1106 + spin_lock_irqsave(&master->devs_lock, flags); 1107 + master->devs[data->index].ibi_dev = NULL; 1108 + spin_unlock_irqrestore(&master->devs_lock, flags); 1109 + 1110 + i3c_generic_ibi_free_pool(data->ibi_pool); 1111 + data->ibi_pool = NULL; 1112 + } 1113 + 1114 + static void dw_i3c_master_set_sir_enabled(struct dw_i3c_master *master, 1115 + struct i3c_dev_desc *dev, 1116 + u8 idx, bool enable) 1117 + { 1118 + unsigned long flags; 1119 + u32 dat_entry, reg; 1120 + bool global; 1121 + 1122 + dat_entry = DEV_ADDR_TABLE_LOC(master->datstartaddr, idx); 1123 + 1124 + spin_lock_irqsave(&master->devs_lock, flags); 1125 + reg = readl(master->regs + dat_entry); 1126 + if (enable) { 1127 + reg &= ~DEV_ADDR_TABLE_SIR_REJECT; 1128 + if (dev->info.bcr & I3C_BCR_IBI_PAYLOAD) 1129 + reg |= DEV_ADDR_TABLE_IBI_MDB; 1130 + } else { 1131 + reg |= DEV_ADDR_TABLE_SIR_REJECT; 1132 + } 1133 + master->platform_ops->set_dat_ibi(master, dev, enable, &reg); 1134 + writel(reg, master->regs + dat_entry); 1135 + 1136 + reg = readl(master->regs + IBI_SIR_REQ_REJECT); 1137 + if (enable) { 1138 + global = reg == 0xffffffff; 1139 + reg &= ~BIT(idx); 1140 + } else { 1141 + global = reg == 0; 1142 + reg |= BIT(idx); 1143 + } 1144 + writel(reg, master->regs + IBI_SIR_REQ_REJECT); 1145 + 1146 + if (global) { 1147 + reg = readl(master->regs + INTR_STATUS_EN); 1148 + reg &= ~INTR_IBI_THLD_STAT; 1149 + if (enable) 1150 + reg |= INTR_IBI_THLD_STAT; 1151 + writel(reg, master->regs + INTR_STATUS_EN); 1152 + 1153 + reg = readl(master->regs + INTR_SIGNAL_EN); 1154 + reg &= ~INTR_IBI_THLD_STAT; 1155 + if (enable) 1156 + reg |= INTR_IBI_THLD_STAT; 1157 + writel(reg, master->regs + INTR_SIGNAL_EN); 1158 + } 1159 + 1160 + spin_unlock_irqrestore(&master->devs_lock, flags); 1161 + } 1162 + 1163 + static int dw_i3c_master_enable_ibi(struct i3c_dev_desc *dev) 1164 + { 1165 + struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); 1166 + struct i3c_master_controller *m = i3c_dev_get_master(dev); 1167 + struct dw_i3c_master *master = to_dw_i3c_master(m); 1168 + int rc; 1169 + 1170 + dw_i3c_master_set_sir_enabled(master, dev, data->index, true); 1171 + 1172 + rc = i3c_master_enec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR); 1173 + 1174 + if (rc) 1175 + dw_i3c_master_set_sir_enabled(master, dev, data->index, false); 1176 + 1177 + return rc; 1178 + } 1179 + 1180 + static int dw_i3c_master_disable_ibi(struct i3c_dev_desc *dev) 1181 + { 1182 + struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); 1183 + struct i3c_master_controller *m = i3c_dev_get_master(dev); 1184 + struct dw_i3c_master *master = to_dw_i3c_master(m); 1185 + int rc; 1186 + 1187 + rc = i3c_master_disec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR); 1188 + if (rc) 1189 + return rc; 1190 + 1191 + dw_i3c_master_set_sir_enabled(master, dev, data->index, false); 1192 + 1193 + return 0; 1194 + } 1195 + 1196 + static void dw_i3c_master_recycle_ibi_slot(struct i3c_dev_desc *dev, 1197 + struct i3c_ibi_slot *slot) 1198 + { 1199 + struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); 1200 + 1201 + i3c_generic_ibi_recycle_slot(data->ibi_pool, slot); 1202 + } 1203 + 1204 + static void dw_i3c_master_drain_ibi_queue(struct dw_i3c_master *master, 1205 + int len) 1206 + { 1207 + int i; 1208 + 1209 + for (i = 0; i < DIV_ROUND_UP(len, 4); i++) 1210 + readl(master->regs + IBI_QUEUE_STATUS); 1211 + } 1212 + 1213 + static void dw_i3c_master_handle_ibi_sir(struct dw_i3c_master *master, 1214 + u32 status) 1215 + { 1216 + struct dw_i3c_i2c_dev_data *data; 1217 + struct i3c_ibi_slot *slot; 1218 + struct i3c_dev_desc *dev; 1219 + unsigned long flags; 1220 + u8 addr, len; 1221 + int idx; 1222 + 1223 + addr = IBI_QUEUE_IBI_ADDR(status); 1224 + len = IBI_QUEUE_STATUS_DATA_LEN(status); 1225 + 1226 + /* 1227 + * We be tempted to check the error status in bit 30; however, due 1228 + * to the PEC errata workaround on some platform implementations (see 1229 + * ast2600_i3c_set_dat_ibi()), those will almost always have a PEC 1230 + * error on IBI payload data, as well as losing the last byte of 1231 + * payload. 1232 + * 1233 + * If we implement error status checking on that bit, we may need 1234 + * a new platform op to validate it. 1235 + */ 1236 + 1237 + spin_lock_irqsave(&master->devs_lock, flags); 1238 + idx = dw_i3c_master_get_addr_pos(master, addr); 1239 + if (idx < 0) { 1240 + dev_dbg_ratelimited(&master->base.dev, 1241 + "IBI from unknown addr 0x%x\n", addr); 1242 + goto err_drain; 1243 + } 1244 + 1245 + dev = master->devs[idx].ibi_dev; 1246 + if (!dev || !dev->ibi) { 1247 + dev_dbg_ratelimited(&master->base.dev, 1248 + "IBI from non-requested dev idx %d\n", idx); 1249 + goto err_drain; 1250 + } 1251 + 1252 + data = i3c_dev_get_master_data(dev); 1253 + slot = i3c_generic_ibi_get_free_slot(data->ibi_pool); 1254 + if (!slot) { 1255 + dev_dbg_ratelimited(&master->base.dev, 1256 + "No IBI slots available\n"); 1257 + goto err_drain; 1258 + } 1259 + 1260 + if (dev->ibi->max_payload_len < len) { 1261 + dev_dbg_ratelimited(&master->base.dev, 1262 + "IBI payload len %d greater than max %d\n", 1263 + len, dev->ibi->max_payload_len); 1264 + goto err_drain; 1265 + } 1266 + 1267 + if (len) { 1268 + dw_i3c_master_read_ibi_fifo(master, slot->data, len); 1269 + slot->len = len; 1270 + } 1271 + i3c_master_queue_ibi(dev, slot); 1272 + 1273 + spin_unlock_irqrestore(&master->devs_lock, flags); 1274 + 1275 + return; 1276 + 1277 + err_drain: 1278 + dw_i3c_master_drain_ibi_queue(master, len); 1279 + 1280 + spin_unlock_irqrestore(&master->devs_lock, flags); 1281 + } 1282 + 1283 + /* "ibis": referring to In-Band Interrupts, and not 1284 + * https://en.wikipedia.org/wiki/Australian_white_ibis. The latter should 1285 + * not be handled. 1286 + */ 1287 + static void dw_i3c_master_irq_handle_ibis(struct dw_i3c_master *master) 1288 + { 1289 + unsigned int i, len, n_ibis; 1290 + u32 reg; 1291 + 1292 + reg = readl(master->regs + QUEUE_STATUS_LEVEL); 1293 + n_ibis = QUEUE_STATUS_IBI_STATUS_CNT(reg); 1294 + if (!n_ibis) 1295 + return; 1296 + 1297 + for (i = 0; i < n_ibis; i++) { 1298 + reg = readl(master->regs + IBI_QUEUE_STATUS); 1299 + 1300 + if (IBI_TYPE_SIRQ(reg)) { 1301 + dw_i3c_master_handle_ibi_sir(master, reg); 1302 + } else { 1303 + len = IBI_QUEUE_STATUS_DATA_LEN(reg); 1304 + dev_info(&master->base.dev, 1305 + "unsupported IBI type 0x%lx len %d\n", 1306 + IBI_QUEUE_STATUS_IBI_ID(reg), len); 1307 + dw_i3c_master_drain_ibi_queue(master, len); 1308 + } 1309 + } 1103 1310 } 1104 1311 1105 1312 static irqreturn_t dw_i3c_master_irq_handler(int irq, void *dev_id) ··· 1352 1095 writel(INTR_TRANSFER_ERR_STAT, master->regs + INTR_STATUS); 1353 1096 spin_unlock(&master->xferqueue.lock); 1354 1097 1098 + if (status & INTR_IBI_THLD_STAT) 1099 + dw_i3c_master_irq_handle_ibis(master); 1100 + 1355 1101 return IRQ_HANDLED; 1356 1102 } 1357 1103 ··· 1373 1113 .i2c_xfers = dw_i3c_master_i2c_xfers, 1374 1114 }; 1375 1115 1376 - static int dw_i3c_probe(struct platform_device *pdev) 1116 + static const struct i3c_master_controller_ops dw_mipi_i3c_ibi_ops = { 1117 + .bus_init = dw_i3c_master_bus_init, 1118 + .bus_cleanup = dw_i3c_master_bus_cleanup, 1119 + .attach_i3c_dev = dw_i3c_master_attach_i3c_dev, 1120 + .reattach_i3c_dev = dw_i3c_master_reattach_i3c_dev, 1121 + .detach_i3c_dev = dw_i3c_master_detach_i3c_dev, 1122 + .do_daa = dw_i3c_master_daa, 1123 + .supports_ccc_cmd = dw_i3c_master_supports_ccc_cmd, 1124 + .send_ccc_cmd = dw_i3c_master_send_ccc_cmd, 1125 + .priv_xfers = dw_i3c_master_priv_xfers, 1126 + .attach_i2c_dev = dw_i3c_master_attach_i2c_dev, 1127 + .detach_i2c_dev = dw_i3c_master_detach_i2c_dev, 1128 + .i2c_xfers = dw_i3c_master_i2c_xfers, 1129 + .request_ibi = dw_i3c_master_request_ibi, 1130 + .free_ibi = dw_i3c_master_free_ibi, 1131 + .enable_ibi = dw_i3c_master_enable_ibi, 1132 + .disable_ibi = dw_i3c_master_disable_ibi, 1133 + .recycle_ibi_slot = dw_i3c_master_recycle_ibi_slot, 1134 + }; 1135 + 1136 + /* default platform ops implementations */ 1137 + static int dw_i3c_platform_init_nop(struct dw_i3c_master *i3c) 1377 1138 { 1378 - struct dw_i3c_master *master; 1139 + return 0; 1140 + } 1141 + 1142 + static void dw_i3c_platform_set_dat_ibi_nop(struct dw_i3c_master *i3c, 1143 + struct i3c_dev_desc *dev, 1144 + bool enable, u32 *dat) 1145 + { 1146 + } 1147 + 1148 + static const struct dw_i3c_platform_ops dw_i3c_platform_ops_default = { 1149 + .init = dw_i3c_platform_init_nop, 1150 + .set_dat_ibi = dw_i3c_platform_set_dat_ibi_nop, 1151 + }; 1152 + 1153 + int dw_i3c_common_probe(struct dw_i3c_master *master, 1154 + struct platform_device *pdev) 1155 + { 1156 + const struct i3c_master_controller_ops *ops; 1379 1157 int ret, irq; 1380 1158 1381 - master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL); 1382 - if (!master) 1383 - return -ENOMEM; 1159 + if (!master->platform_ops) 1160 + master->platform_ops = &dw_i3c_platform_ops_default; 1384 1161 1385 1162 master->regs = devm_platform_ioremap_resource(pdev, 0); 1386 1163 if (IS_ERR(master->regs)) ··· 1463 1166 master->maxdevs = ret >> 16; 1464 1167 master->free_pos = GENMASK(master->maxdevs - 1, 0); 1465 1168 1466 - ret = i3c_master_register(&master->base, &pdev->dev, 1467 - &dw_mipi_i3c_ops, false); 1169 + ops = &dw_mipi_i3c_ops; 1170 + if (master->ibi_capable) 1171 + ops = &dw_mipi_i3c_ibi_ops; 1172 + 1173 + ret = i3c_master_register(&master->base, &pdev->dev, ops, false); 1468 1174 if (ret) 1469 1175 goto err_assert_rst; 1470 1176 ··· 1481 1181 1482 1182 return ret; 1483 1183 } 1184 + EXPORT_SYMBOL_GPL(dw_i3c_common_probe); 1484 1185 1485 - static int dw_i3c_remove(struct platform_device *pdev) 1186 + void dw_i3c_common_remove(struct dw_i3c_master *master) 1486 1187 { 1487 - struct dw_i3c_master *master = platform_get_drvdata(pdev); 1488 - int ret; 1489 - 1490 - ret = i3c_master_unregister(&master->base); 1491 - if (ret) 1492 - return ret; 1188 + i3c_master_unregister(&master->base); 1493 1189 1494 1190 reset_control_assert(master->core_rst); 1495 1191 1496 1192 clk_disable_unprepare(master->core_clk); 1193 + } 1194 + EXPORT_SYMBOL_GPL(dw_i3c_common_remove); 1497 1195 1498 - return 0; 1196 + /* base platform implementation */ 1197 + 1198 + static int dw_i3c_probe(struct platform_device *pdev) 1199 + { 1200 + struct dw_i3c_master *master; 1201 + 1202 + master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL); 1203 + if (!master) 1204 + return -ENOMEM; 1205 + 1206 + return dw_i3c_common_probe(master, pdev); 1207 + } 1208 + 1209 + static void dw_i3c_remove(struct platform_device *pdev) 1210 + { 1211 + struct dw_i3c_master *master = platform_get_drvdata(pdev); 1212 + 1213 + dw_i3c_common_remove(master); 1499 1214 } 1500 1215 1501 1216 static const struct of_device_id dw_i3c_master_of_match[] = { ··· 1521 1206 1522 1207 static struct platform_driver dw_i3c_driver = { 1523 1208 .probe = dw_i3c_probe, 1524 - .remove = dw_i3c_remove, 1209 + .remove_new = dw_i3c_remove, 1525 1210 .driver = { 1526 1211 .name = "dw-i3c-master", 1527 - .of_match_table = of_match_ptr(dw_i3c_master_of_match), 1212 + .of_match_table = dw_i3c_master_of_match, 1528 1213 }, 1529 1214 }; 1530 1215 module_platform_driver(dw_i3c_driver);
+84
drivers/i3c/master/dw-i3c-master.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2023 Code Construct 4 + * 5 + * Author: Jeremy Kerr <jk@codeconstruct.com.au> 6 + */ 7 + 8 + #include <linux/clk.h> 9 + #include <linux/i3c/master.h> 10 + #include <linux/reset.h> 11 + #include <linux/types.h> 12 + 13 + #define DW_I3C_MAX_DEVS 32 14 + 15 + struct dw_i3c_master_caps { 16 + u8 cmdfifodepth; 17 + u8 datafifodepth; 18 + }; 19 + 20 + struct dw_i3c_dat_entry { 21 + u8 addr; 22 + struct i3c_dev_desc *ibi_dev; 23 + }; 24 + 25 + struct dw_i3c_master { 26 + struct i3c_master_controller base; 27 + u16 maxdevs; 28 + u16 datstartaddr; 29 + u32 free_pos; 30 + struct { 31 + struct list_head list; 32 + struct dw_i3c_xfer *cur; 33 + spinlock_t lock; 34 + } xferqueue; 35 + struct dw_i3c_master_caps caps; 36 + void __iomem *regs; 37 + struct reset_control *core_rst; 38 + struct clk *core_clk; 39 + char version[5]; 40 + char type[5]; 41 + bool ibi_capable; 42 + 43 + /* 44 + * Per-device hardware data, used to manage the device address table 45 + * (DAT) 46 + * 47 + * Locking: the devs array may be referenced in IRQ context while 48 + * processing an IBI. However, IBIs (for a specific device, which 49 + * implies a specific DAT entry) can only happen while interrupts are 50 + * requested for that device, which is serialised against other 51 + * insertions/removals from the array by the global i3c infrastructure. 52 + * So, devs_lock protects against concurrent updates to devs->ibi_dev 53 + * between request_ibi/free_ibi and the IBI irq event. 54 + */ 55 + struct dw_i3c_dat_entry devs[DW_I3C_MAX_DEVS]; 56 + spinlock_t devs_lock; 57 + 58 + /* platform-specific data */ 59 + const struct dw_i3c_platform_ops *platform_ops; 60 + }; 61 + 62 + struct dw_i3c_platform_ops { 63 + /* 64 + * Called on early bus init: the i3c has been set up, but before any 65 + * transactions have taken place. Platform implementations may use to 66 + * perform actual device enabling with the i3c core ready. 67 + */ 68 + int (*init)(struct dw_i3c_master *i3c); 69 + 70 + /* 71 + * Initialise a DAT entry to enable/disable IBIs. Allows the platform 72 + * to perform any device workarounds on the DAT entry before 73 + * inserting into the hardware table. 74 + * 75 + * Called with the DAT lock held; must not sleep. 76 + */ 77 + void (*set_dat_ibi)(struct dw_i3c_master *i3c, 78 + struct i3c_dev_desc *dev, bool enable, u32 *reg); 79 + }; 80 + 81 + extern int dw_i3c_common_probe(struct dw_i3c_master *master, 82 + struct platform_device *pdev); 83 + extern void dw_i3c_common_remove(struct dw_i3c_master *master); 84 +
+3 -8
drivers/i3c/master/i3c-master-cdns.c
··· 1662 1662 return ret; 1663 1663 } 1664 1664 1665 - static int cdns_i3c_master_remove(struct platform_device *pdev) 1665 + static void cdns_i3c_master_remove(struct platform_device *pdev) 1666 1666 { 1667 1667 struct cdns_i3c_master *master = platform_get_drvdata(pdev); 1668 - int ret; 1669 1668 1670 - ret = i3c_master_unregister(&master->base); 1671 - if (ret) 1672 - return ret; 1669 + i3c_master_unregister(&master->base); 1673 1670 1674 1671 clk_disable_unprepare(master->sysclk); 1675 1672 clk_disable_unprepare(master->pclk); 1676 - 1677 - return 0; 1678 1673 } 1679 1674 1680 1675 static struct platform_driver cdns_i3c_master = { 1681 1676 .probe = cdns_i3c_master_probe, 1682 - .remove = cdns_i3c_master_remove, 1677 + .remove_new = cdns_i3c_master_remove, 1683 1678 .driver = { 1684 1679 .name = "cdns-i3c-master", 1685 1680 .of_match_table = cdns_i3c_master_of_ids,
+3 -3
drivers/i3c/master/mipi-i3c-hci/core.c
··· 765 765 return 0; 766 766 } 767 767 768 - static int i3c_hci_remove(struct platform_device *pdev) 768 + static void i3c_hci_remove(struct platform_device *pdev) 769 769 { 770 770 struct i3c_hci *hci = platform_get_drvdata(pdev); 771 771 772 - return i3c_master_unregister(&hci->master); 772 + i3c_master_unregister(&hci->master); 773 773 } 774 774 775 775 static const __maybe_unused struct of_device_id i3c_hci_of_match[] = { ··· 780 780 781 781 static struct platform_driver i3c_hci_driver = { 782 782 .probe = i3c_hci_probe, 783 - .remove = i3c_hci_remove, 783 + .remove_new = i3c_hci_remove, 784 784 .driver = { 785 785 .name = "mipi-i3c-hci", 786 786 .of_match_table = of_match_ptr(i3c_hci_of_match),
+3 -8
drivers/i3c/master/svc-i3c-master.c
··· 1569 1569 return ret; 1570 1570 } 1571 1571 1572 - static int svc_i3c_master_remove(struct platform_device *pdev) 1572 + static void svc_i3c_master_remove(struct platform_device *pdev) 1573 1573 { 1574 1574 struct svc_i3c_master *master = platform_get_drvdata(pdev); 1575 - int ret; 1576 1575 1577 - ret = i3c_master_unregister(&master->base); 1578 - if (ret) 1579 - return ret; 1576 + i3c_master_unregister(&master->base); 1580 1577 1581 1578 pm_runtime_dont_use_autosuspend(&pdev->dev); 1582 1579 pm_runtime_disable(&pdev->dev); 1583 - 1584 - return 0; 1585 1580 } 1586 1581 1587 1582 static int __maybe_unused svc_i3c_runtime_suspend(struct device *dev) ··· 1614 1619 1615 1620 static struct platform_driver svc_i3c_master = { 1616 1621 .probe = svc_i3c_master_probe, 1617 - .remove = svc_i3c_master_remove, 1622 + .remove_new = svc_i3c_master_remove, 1618 1623 .driver = { 1619 1624 .name = "silvaco-i3c-master", 1620 1625 .of_match_table = svc_i3c_master_of_match_tbl,
+3 -2
include/linux/i3c/master.h
··· 22 22 #define I3C_BROADCAST_ADDR 0x7e 23 23 #define I3C_MAX_ADDR GENMASK(6, 0) 24 24 25 + struct i2c_client; 26 + 25 27 struct i3c_master_controller; 26 28 struct i3c_bus; 27 - struct i2c_device; 28 29 struct i3c_device; 29 30 30 31 /** ··· 542 541 struct device *parent, 543 542 const struct i3c_master_controller_ops *ops, 544 543 bool secondary); 545 - int i3c_master_unregister(struct i3c_master_controller *master); 544 + void i3c_master_unregister(struct i3c_master_controller *master); 546 545 547 546 /** 548 547 * i3c_dev_get_master_data() - get master private data attached to an I3C