1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3  * Copyright (c) 2020, MIPI Alliance, Inc.
4  *
5  * Author: Nicolas Pitre <[email protected]>
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 
hci_dat_v1_init(struct i3c_hci * hci)43 static int hci_dat_v1_init(struct i3c_hci *hci)
44 {
45 	unsigned int dat_idx;
46 
47 	if (!hci->DAT_regs) {
48 		dev_err(&hci->master.dev,
49 			"only DAT in register space is supported at the moment\n");
50 		return -EOPNOTSUPP;
51 	}
52 	if (hci->DAT_entry_size != 8) {
53 		dev_err(&hci->master.dev,
54 			"only 8-bytes DAT entries are supported at the moment\n");
55 		return -EOPNOTSUPP;
56 	}
57 
58 	if (!hci->DAT_data) {
59 		/* use a bitmap for faster free slot search */
60 		hci->DAT_data = bitmap_zalloc(hci->DAT_entries, GFP_KERNEL);
61 		if (!hci->DAT_data)
62 			return -ENOMEM;
63 
64 		/* clear them */
65 		for (dat_idx = 0; dat_idx < hci->DAT_entries; dat_idx++) {
66 			dat_w0_write(dat_idx, 0);
67 			dat_w1_write(dat_idx, 0);
68 		}
69 	}
70 
71 	return 0;
72 }
73 
hci_dat_v1_cleanup(struct i3c_hci * hci)74 static void hci_dat_v1_cleanup(struct i3c_hci *hci)
75 {
76 	bitmap_free(hci->DAT_data);
77 	hci->DAT_data = NULL;
78 }
79 
hci_dat_v1_alloc_entry(struct i3c_hci * hci)80 static int hci_dat_v1_alloc_entry(struct i3c_hci *hci)
81 {
82 	unsigned int dat_idx;
83 	int ret;
84 
85 	if (!hci->DAT_data) {
86 		ret = hci_dat_v1_init(hci);
87 		if (ret)
88 			return ret;
89 	}
90 	dat_idx = find_first_zero_bit(hci->DAT_data, hci->DAT_entries);
91 	if (dat_idx >= hci->DAT_entries)
92 		return -ENOENT;
93 	__set_bit(dat_idx, hci->DAT_data);
94 
95 	/* default flags */
96 	dat_w0_write(dat_idx, DAT_0_SIR_REJECT | DAT_0_MR_REJECT);
97 
98 	return dat_idx;
99 }
100 
hci_dat_v1_free_entry(struct i3c_hci * hci,unsigned int dat_idx)101 static void hci_dat_v1_free_entry(struct i3c_hci *hci, unsigned int dat_idx)
102 {
103 	dat_w0_write(dat_idx, 0);
104 	dat_w1_write(dat_idx, 0);
105 	if (hci->DAT_data)
106 		__clear_bit(dat_idx, hci->DAT_data);
107 }
108 
hci_dat_v1_set_dynamic_addr(struct i3c_hci * hci,unsigned int dat_idx,u8 address)109 static void hci_dat_v1_set_dynamic_addr(struct i3c_hci *hci,
110 					unsigned int dat_idx, u8 address)
111 {
112 	u32 dat_w0;
113 
114 	dat_w0 = dat_w0_read(dat_idx);
115 	dat_w0 &= ~(DAT_0_DYNAMIC_ADDRESS | DAT_0_DYNADDR_PARITY);
116 	dat_w0 |= FIELD_PREP(DAT_0_DYNAMIC_ADDRESS, address) |
117 		  (parity8(address) ? 0 : DAT_0_DYNADDR_PARITY);
118 	dat_w0_write(dat_idx, dat_w0);
119 }
120 
hci_dat_v1_set_static_addr(struct i3c_hci * hci,unsigned int dat_idx,u8 address)121 static void hci_dat_v1_set_static_addr(struct i3c_hci *hci,
122 				       unsigned int dat_idx, u8 address)
123 {
124 	u32 dat_w0;
125 
126 	dat_w0 = dat_w0_read(dat_idx);
127 	dat_w0 &= ~DAT_0_STATIC_ADDRESS;
128 	dat_w0 |= FIELD_PREP(DAT_0_STATIC_ADDRESS, address);
129 	dat_w0_write(dat_idx, dat_w0);
130 }
131 
hci_dat_v1_set_flags(struct i3c_hci * hci,unsigned int dat_idx,u32 w0_flags,u32 w1_flags)132 static void hci_dat_v1_set_flags(struct i3c_hci *hci, unsigned int dat_idx,
133 				 u32 w0_flags, u32 w1_flags)
134 {
135 	u32 dat_w0, dat_w1;
136 
137 	dat_w0 = dat_w0_read(dat_idx);
138 	dat_w1 = dat_w1_read(dat_idx);
139 	dat_w0 |= w0_flags;
140 	dat_w1 |= w1_flags;
141 	dat_w0_write(dat_idx, dat_w0);
142 	dat_w1_write(dat_idx, dat_w1);
143 }
144 
hci_dat_v1_clear_flags(struct i3c_hci * hci,unsigned int dat_idx,u32 w0_flags,u32 w1_flags)145 static void hci_dat_v1_clear_flags(struct i3c_hci *hci, unsigned int dat_idx,
146 				   u32 w0_flags, u32 w1_flags)
147 {
148 	u32 dat_w0, dat_w1;
149 
150 	dat_w0 = dat_w0_read(dat_idx);
151 	dat_w1 = dat_w1_read(dat_idx);
152 	dat_w0 &= ~w0_flags;
153 	dat_w1 &= ~w1_flags;
154 	dat_w0_write(dat_idx, dat_w0);
155 	dat_w1_write(dat_idx, dat_w1);
156 }
157 
hci_dat_v1_get_index(struct i3c_hci * hci,u8 dev_addr)158 static int hci_dat_v1_get_index(struct i3c_hci *hci, u8 dev_addr)
159 {
160 	unsigned int dat_idx;
161 	u32 dat_w0;
162 
163 	for_each_set_bit(dat_idx, hci->DAT_data, hci->DAT_entries) {
164 		dat_w0 = dat_w0_read(dat_idx);
165 		if (FIELD_GET(DAT_0_DYNAMIC_ADDRESS, dat_w0) == dev_addr)
166 			return dat_idx;
167 	}
168 
169 	return -ENODEV;
170 }
171 
172 const struct hci_dat_ops mipi_i3c_hci_dat_v1 = {
173 	.init			= hci_dat_v1_init,
174 	.cleanup		= hci_dat_v1_cleanup,
175 	.alloc_entry		= hci_dat_v1_alloc_entry,
176 	.free_entry		= hci_dat_v1_free_entry,
177 	.set_dynamic_addr	= hci_dat_v1_set_dynamic_addr,
178 	.set_static_addr	= hci_dat_v1_set_static_addr,
179 	.set_flags		= hci_dat_v1_set_flags,
180 	.clear_flags		= hci_dat_v1_clear_flags,
181 	.get_index		= hci_dat_v1_get_index,
182 };
183