1 // SPDX-License-Identifier: BSD-3-Clause 2 /* 3 * Copyright (c) 2020, MIPI Alliance, Inc. 4 * 5 * Author: Nicolas Pitre <npitre@baylibre.com> 6 */ 7 8 #include <linux/bitfield.h> 9 #include <linux/bitmap.h> 10 #include <linux/device.h> 11 #include <linux/errno.h> 12 #include <linux/i3c/master.h> 13 #include <linux/io.h> 14 15 #include "hci.h" 16 #include "dat.h" 17 18 19 /* 20 * Device Address Table Structure 21 */ 22 23 #define DAT_1_AUTOCMD_HDR_CODE W1_MASK(58, 51) 24 #define DAT_1_AUTOCMD_MODE W1_MASK(50, 48) 25 #define DAT_1_AUTOCMD_VALUE W1_MASK(47, 40) 26 #define DAT_1_AUTOCMD_MASK W1_MASK(39, 32) 27 /* DAT_0_I2C_DEVICE W0_BIT_(31) */ 28 #define DAT_0_DEV_NACK_RETRY_CNT W0_MASK(30, 29) 29 #define DAT_0_RING_ID W0_MASK(28, 26) 30 #define DAT_0_DYNADDR_PARITY W0_BIT_(23) 31 #define DAT_0_DYNAMIC_ADDRESS W0_MASK(22, 16) 32 #define DAT_0_TS W0_BIT_(15) 33 #define DAT_0_MR_REJECT W0_BIT_(14) 34 /* DAT_0_SIR_REJECT W0_BIT_(13) */ 35 /* DAT_0_IBI_PAYLOAD W0_BIT_(12) */ 36 #define DAT_0_STATIC_ADDRESS W0_MASK(6, 0) 37 38 #define dat_w0_read(i) readl(hci->DAT_regs + (i) * 8) 39 #define dat_w1_read(i) readl(hci->DAT_regs + (i) * 8 + 4) 40 #define dat_w0_write(i, v) writel(v, hci->DAT_regs + (i) * 8) 41 #define dat_w1_write(i, v) writel(v, hci->DAT_regs + (i) * 8 + 4) 42 43 static inline bool dynaddr_parity(unsigned int addr) 44 { 45 addr |= 1 << 7; 46 addr += addr >> 4; 47 addr += addr >> 2; 48 addr += addr >> 1; 49 return (addr & 1); 50 } 51 52 static int hci_dat_v1_init(struct i3c_hci *hci) 53 { 54 unsigned int dat_idx; 55 56 if (!hci->DAT_regs) { 57 dev_err(&hci->master.dev, 58 "only DAT in register space is supported at the moment\n"); 59 return -EOPNOTSUPP; 60 } 61 if (hci->DAT_entry_size != 8) { 62 dev_err(&hci->master.dev, 63 "only 8-bytes DAT entries are supported at the moment\n"); 64 return -EOPNOTSUPP; 65 } 66 67 if (!hci->DAT_data) { 68 /* use a bitmap for faster free slot search */ 69 hci->DAT_data = bitmap_zalloc(hci->DAT_entries, GFP_KERNEL); 70 if (!hci->DAT_data) 71 return -ENOMEM; 72 73 /* clear them */ 74 for (dat_idx = 0; dat_idx < hci->DAT_entries; dat_idx++) { 75 dat_w0_write(dat_idx, 0); 76 dat_w1_write(dat_idx, 0); 77 } 78 } 79 80 return 0; 81 } 82 83 static void hci_dat_v1_cleanup(struct i3c_hci *hci) 84 { 85 bitmap_free(hci->DAT_data); 86 hci->DAT_data = NULL; 87 } 88 89 static int hci_dat_v1_alloc_entry(struct i3c_hci *hci) 90 { 91 unsigned int dat_idx; 92 int ret; 93 94 if (!hci->DAT_data) { 95 ret = hci_dat_v1_init(hci); 96 if (ret) 97 return ret; 98 } 99 dat_idx = find_first_zero_bit(hci->DAT_data, hci->DAT_entries); 100 if (dat_idx >= hci->DAT_entries) 101 return -ENOENT; 102 __set_bit(dat_idx, hci->DAT_data); 103 104 /* default flags */ 105 dat_w0_write(dat_idx, DAT_0_SIR_REJECT | DAT_0_MR_REJECT); 106 107 return dat_idx; 108 } 109 110 static void hci_dat_v1_free_entry(struct i3c_hci *hci, unsigned int dat_idx) 111 { 112 dat_w0_write(dat_idx, 0); 113 dat_w1_write(dat_idx, 0); 114 if (hci->DAT_data) 115 __clear_bit(dat_idx, hci->DAT_data); 116 } 117 118 static void hci_dat_v1_set_dynamic_addr(struct i3c_hci *hci, 119 unsigned int dat_idx, u8 address) 120 { 121 u32 dat_w0; 122 123 dat_w0 = dat_w0_read(dat_idx); 124 dat_w0 &= ~(DAT_0_DYNAMIC_ADDRESS | DAT_0_DYNADDR_PARITY); 125 dat_w0 |= FIELD_PREP(DAT_0_DYNAMIC_ADDRESS, address) | 126 (dynaddr_parity(address) ? DAT_0_DYNADDR_PARITY : 0); 127 dat_w0_write(dat_idx, dat_w0); 128 } 129 130 static void hci_dat_v1_set_static_addr(struct i3c_hci *hci, 131 unsigned int dat_idx, u8 address) 132 { 133 u32 dat_w0; 134 135 dat_w0 = dat_w0_read(dat_idx); 136 dat_w0 &= ~DAT_0_STATIC_ADDRESS; 137 dat_w0 |= FIELD_PREP(DAT_0_STATIC_ADDRESS, address); 138 dat_w0_write(dat_idx, dat_w0); 139 } 140 141 static void hci_dat_v1_set_flags(struct i3c_hci *hci, unsigned int dat_idx, 142 u32 w0_flags, u32 w1_flags) 143 { 144 u32 dat_w0, dat_w1; 145 146 dat_w0 = dat_w0_read(dat_idx); 147 dat_w1 = dat_w1_read(dat_idx); 148 dat_w0 |= w0_flags; 149 dat_w1 |= w1_flags; 150 dat_w0_write(dat_idx, dat_w0); 151 dat_w1_write(dat_idx, dat_w1); 152 } 153 154 static void hci_dat_v1_clear_flags(struct i3c_hci *hci, unsigned int dat_idx, 155 u32 w0_flags, u32 w1_flags) 156 { 157 u32 dat_w0, dat_w1; 158 159 dat_w0 = dat_w0_read(dat_idx); 160 dat_w1 = dat_w1_read(dat_idx); 161 dat_w0 &= ~w0_flags; 162 dat_w1 &= ~w1_flags; 163 dat_w0_write(dat_idx, dat_w0); 164 dat_w1_write(dat_idx, dat_w1); 165 } 166 167 static int hci_dat_v1_get_index(struct i3c_hci *hci, u8 dev_addr) 168 { 169 unsigned int dat_idx; 170 u32 dat_w0; 171 172 for_each_set_bit(dat_idx, hci->DAT_data, hci->DAT_entries) { 173 dat_w0 = dat_w0_read(dat_idx); 174 if (FIELD_GET(DAT_0_DYNAMIC_ADDRESS, dat_w0) == dev_addr) 175 return dat_idx; 176 } 177 178 return -ENODEV; 179 } 180 181 const struct hci_dat_ops mipi_i3c_hci_dat_v1 = { 182 .init = hci_dat_v1_init, 183 .cleanup = hci_dat_v1_cleanup, 184 .alloc_entry = hci_dat_v1_alloc_entry, 185 .free_entry = hci_dat_v1_free_entry, 186 .set_dynamic_addr = hci_dat_v1_set_dynamic_addr, 187 .set_static_addr = hci_dat_v1_set_static_addr, 188 .set_flags = hci_dat_v1_set_flags, 189 .clear_flags = hci_dat_v1_clear_flags, 190 .get_index = hci_dat_v1_get_index, 191 }; 192