1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * amd_axi_w1 - AMD 1Wire programmable logic bus host driver |
4 | * |
5 | * Copyright (C) 2022-2023 Advanced Micro Devices, Inc. All Rights Reserved. |
6 | */ |
7 | |
8 | #include <linux/atomic.h> |
9 | #include <linux/bitfield.h> |
10 | #include <linux/clk.h> |
11 | #include <linux/interrupt.h> |
12 | #include <linux/io.h> |
13 | #include <linux/jiffies.h> |
14 | #include <linux/kernel.h> |
15 | #include <linux/mod_devicetable.h> |
16 | #include <linux/module.h> |
17 | #include <linux/platform_device.h> |
18 | #include <linux/types.h> |
19 | #include <linux/wait.h> |
20 | |
21 | #include <linux/w1.h> |
22 | |
23 | /* 1-wire AMD IP definition */ |
24 | #define AXIW1_IPID 0x10ee4453 |
25 | /* Registers offset */ |
26 | #define AXIW1_INST_REG 0x0 |
27 | #define AXIW1_CTRL_REG 0x4 |
28 | #define AXIW1_IRQE_REG 0x8 |
29 | #define AXIW1_STAT_REG 0xC |
30 | #define AXIW1_DATA_REG 0x10 |
31 | #define AXIW1_IPVER_REG 0x18 |
32 | #define AXIW1_IPID_REG 0x1C |
33 | /* Instructions */ |
34 | #define AXIW1_INITPRES 0x0800 |
35 | #define AXIW1_READBIT 0x0C00 |
36 | #define AXIW1_WRITEBIT 0x0E00 |
37 | #define AXIW1_READBYTE 0x0D00 |
38 | #define AXIW1_WRITEBYTE 0x0F00 |
39 | /* Status flag masks */ |
40 | #define AXIW1_DONE BIT(0) |
41 | #define AXIW1_READY BIT(4) |
42 | #define AXIW1_PRESENCE BIT(31) |
43 | #define AXIW1_MAJORVER_MASK GENMASK(23, 8) |
44 | #define AXIW1_MINORVER_MASK GENMASK(7, 0) |
45 | /* Control flag */ |
46 | #define AXIW1_GO BIT(0) |
47 | #define AXI_CLEAR 0 |
48 | #define AXI_RESET BIT(31) |
49 | #define AXIW1_READDATA BIT(0) |
50 | /* Interrupt Enable */ |
51 | #define AXIW1_READY_IRQ_EN BIT(4) |
52 | #define AXIW1_DONE_IRQ_EN BIT(0) |
53 | |
54 | #define AXIW1_TIMEOUT msecs_to_jiffies(100) |
55 | |
56 | #define DRIVER_NAME "amd_axi_w1" |
57 | |
58 | struct amd_axi_w1_local { |
59 | struct device *dev; |
60 | void __iomem *base_addr; |
61 | int irq; |
62 | atomic_t flag; /* Set on IRQ, cleared once serviced */ |
63 | wait_queue_head_t wait_queue; |
64 | struct w1_bus_master bus_host; |
65 | }; |
66 | |
67 | /** |
68 | * amd_axi_w1_wait_irq_interruptible_timeout() - Wait for IRQ with timeout. |
69 | * |
70 | * @amd_axi_w1_local: Pointer to device structure |
71 | * @IRQ: IRQ channel to wait on |
72 | * |
73 | * Return: %0 - OK, %-EINTR - Interrupted, %-EBUSY - Timed out |
74 | */ |
75 | static int amd_axi_w1_wait_irq_interruptible_timeout(struct amd_axi_w1_local *amd_axi_w1_local, |
76 | u32 IRQ) |
77 | { |
78 | int ret; |
79 | |
80 | /* Enable the IRQ requested and wait for flag to indicate it's been triggered */ |
81 | iowrite32(IRQ, amd_axi_w1_local->base_addr + AXIW1_IRQE_REG); |
82 | ret = wait_event_interruptible_timeout(amd_axi_w1_local->wait_queue, |
83 | atomic_read(&amd_axi_w1_local->flag) != 0, |
84 | AXIW1_TIMEOUT); |
85 | if (ret < 0) { |
86 | dev_err(amd_axi_w1_local->dev, "Wait IRQ Interrupted\n" ); |
87 | return -EINTR; |
88 | } |
89 | |
90 | if (!ret) { |
91 | dev_err(amd_axi_w1_local->dev, "Wait IRQ Timeout\n" ); |
92 | return -EBUSY; |
93 | } |
94 | |
95 | atomic_set(v: &amd_axi_w1_local->flag, i: 0); |
96 | return 0; |
97 | } |
98 | |
99 | /** |
100 | * amd_axi_w1_touch_bit() - Performs the touch-bit function - write a 0 or 1 and reads the level. |
101 | * |
102 | * @data: Pointer to device structure |
103 | * @bit: The level to write |
104 | * |
105 | * Return: The level read |
106 | */ |
107 | static u8 amd_axi_w1_touch_bit(void *data, u8 bit) |
108 | { |
109 | struct amd_axi_w1_local *amd_axi_w1_local = data; |
110 | u8 val = 0; |
111 | int rc; |
112 | |
113 | /* Wait for READY signal to be 1 to ensure 1-wire IP is ready */ |
114 | while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_READY) == 0) { |
115 | rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local, |
116 | AXIW1_READY_IRQ_EN); |
117 | if (rc < 0) |
118 | return 1; /* Callee doesn't test for error. Return inactive bus state */ |
119 | } |
120 | |
121 | if (bit) |
122 | /* Read. Write read Bit command in register 0 */ |
123 | iowrite32(AXIW1_READBIT, amd_axi_w1_local->base_addr + AXIW1_INST_REG); |
124 | else |
125 | /* Write. Write tx Bit command in instruction register with bit to transmit */ |
126 | iowrite32(AXIW1_WRITEBIT + (bit & 0x01), |
127 | amd_axi_w1_local->base_addr + AXIW1_INST_REG); |
128 | |
129 | /* Write Go signal and clear control reset signal in control register */ |
130 | iowrite32(AXIW1_GO, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG); |
131 | |
132 | /* Wait for done signal to be 1 */ |
133 | while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_DONE) != 1) { |
134 | rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local, AXIW1_DONE_IRQ_EN); |
135 | if (rc < 0) |
136 | return 1; /* Callee doesn't test for error. Return inactive bus state */ |
137 | } |
138 | |
139 | /* If read, Retrieve data from register */ |
140 | if (bit) |
141 | val = (u8)(ioread32(amd_axi_w1_local->base_addr + AXIW1_DATA_REG) & AXIW1_READDATA); |
142 | |
143 | /* Clear Go signal in register 1 */ |
144 | iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG); |
145 | |
146 | return val; |
147 | } |
148 | |
149 | /** |
150 | * amd_axi_w1_read_byte - Performs the read byte function. |
151 | * |
152 | * @data: Pointer to device structure |
153 | * Return: The value read |
154 | */ |
155 | static u8 amd_axi_w1_read_byte(void *data) |
156 | { |
157 | struct amd_axi_w1_local *amd_axi_w1_local = data; |
158 | u8 val = 0; |
159 | int rc; |
160 | |
161 | /* Wait for READY signal to be 1 to ensure 1-wire IP is ready */ |
162 | while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_READY) == 0) { |
163 | rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local, |
164 | AXIW1_READY_IRQ_EN); |
165 | if (rc < 0) |
166 | return 0xFF; /* Return inactive bus state */ |
167 | } |
168 | |
169 | /* Write read Byte command in instruction register*/ |
170 | iowrite32(AXIW1_READBYTE, amd_axi_w1_local->base_addr + AXIW1_INST_REG); |
171 | |
172 | /* Write Go signal and clear control reset signal in control register */ |
173 | iowrite32(AXIW1_GO, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG); |
174 | |
175 | /* Wait for done signal to be 1 */ |
176 | while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_DONE) != 1) { |
177 | rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local, AXIW1_DONE_IRQ_EN); |
178 | if (rc < 0) |
179 | return 0xFF; /* Return inactive bus state */ |
180 | } |
181 | |
182 | /* Retrieve LSB bit in data register to get RX byte */ |
183 | val = (u8)(ioread32(amd_axi_w1_local->base_addr + AXIW1_DATA_REG) & 0x000000FF); |
184 | |
185 | /* Clear Go signal in control register */ |
186 | iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG); |
187 | |
188 | return val; |
189 | } |
190 | |
191 | /** |
192 | * amd_axi_w1_write_byte - Performs the write byte function. |
193 | * |
194 | * @data: The ds2482 channel pointer |
195 | * @val: The value to write |
196 | */ |
197 | static void amd_axi_w1_write_byte(void *data, u8 val) |
198 | { |
199 | struct amd_axi_w1_local *amd_axi_w1_local = data; |
200 | int rc; |
201 | |
202 | /* Wait for READY signal to be 1 to ensure 1-wire IP is ready */ |
203 | while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_READY) == 0) { |
204 | rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local, |
205 | AXIW1_READY_IRQ_EN); |
206 | if (rc < 0) |
207 | return; |
208 | } |
209 | |
210 | /* Write tx Byte command in instruction register with bit to transmit */ |
211 | iowrite32(AXIW1_WRITEBYTE + val, amd_axi_w1_local->base_addr + AXIW1_INST_REG); |
212 | |
213 | /* Write Go signal and clear control reset signal in register 1 */ |
214 | iowrite32(AXIW1_GO, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG); |
215 | |
216 | /* Wait for done signal to be 1 */ |
217 | while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_DONE) != 1) { |
218 | rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local, |
219 | AXIW1_DONE_IRQ_EN); |
220 | if (rc < 0) |
221 | return; |
222 | } |
223 | |
224 | /* Clear Go signal in control register */ |
225 | iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG); |
226 | } |
227 | |
228 | /** |
229 | * amd_axi_w1_reset_bus() - Issues a reset bus sequence. |
230 | * |
231 | * @data: the bus host data struct |
232 | * Return: 0=Device present, 1=No device present or error |
233 | */ |
234 | static u8 amd_axi_w1_reset_bus(void *data) |
235 | { |
236 | struct amd_axi_w1_local *amd_axi_w1_local = data; |
237 | u8 val = 0; |
238 | int rc; |
239 | |
240 | /* Reset 1-wire Axi IP */ |
241 | iowrite32(AXI_RESET, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG); |
242 | |
243 | /* Wait for READY signal to be 1 to ensure 1-wire IP is ready */ |
244 | while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_READY) == 0) { |
245 | rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local, |
246 | AXIW1_READY_IRQ_EN); |
247 | if (rc < 0) |
248 | return 1; /* Something went wrong with the hardware */ |
249 | } |
250 | /* Write Initialization command in instruction register */ |
251 | iowrite32(AXIW1_INITPRES, amd_axi_w1_local->base_addr + AXIW1_INST_REG); |
252 | |
253 | /* Write Go signal and clear control reset signal in register 1 */ |
254 | iowrite32(AXIW1_GO, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG); |
255 | |
256 | /* Wait for done signal to be 1 */ |
257 | while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_DONE) != 1) { |
258 | rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local, AXIW1_DONE_IRQ_EN); |
259 | if (rc < 0) |
260 | return 1; /* Something went wrong with the hardware */ |
261 | } |
262 | /* Retrieve MSB bit in status register to get failure bit */ |
263 | if ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_PRESENCE) != 0) |
264 | val = 1; |
265 | |
266 | /* Clear Go signal in control register */ |
267 | iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG); |
268 | |
269 | return val; |
270 | } |
271 | |
272 | /* Reset the 1-wire AXI IP. Put the IP in reset state and clear registers */ |
273 | static void amd_axi_w1_reset(struct amd_axi_w1_local *amd_axi_w1_local) |
274 | { |
275 | iowrite32(AXI_RESET, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG); |
276 | iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_INST_REG); |
277 | iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_IRQE_REG); |
278 | iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_STAT_REG); |
279 | iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_DATA_REG); |
280 | } |
281 | |
282 | static irqreturn_t amd_axi_w1_irq(int irq, void *lp) |
283 | { |
284 | struct amd_axi_w1_local *amd_axi_w1_local = lp; |
285 | |
286 | /* Reset interrupt trigger */ |
287 | iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_IRQE_REG); |
288 | |
289 | atomic_set(v: &amd_axi_w1_local->flag, i: 1); |
290 | wake_up_interruptible(&amd_axi_w1_local->wait_queue); |
291 | |
292 | return IRQ_HANDLED; |
293 | } |
294 | |
295 | static int amd_axi_w1_probe(struct platform_device *pdev) |
296 | { |
297 | struct device *dev = &pdev->dev; |
298 | struct amd_axi_w1_local *lp; |
299 | struct clk *clk; |
300 | u32 ver_major, ver_minor; |
301 | int val, rc = 0; |
302 | |
303 | lp = devm_kzalloc(dev, size: sizeof(*lp), GFP_KERNEL); |
304 | if (!lp) |
305 | return -ENOMEM; |
306 | |
307 | lp->dev = dev; |
308 | lp->base_addr = devm_platform_ioremap_resource(pdev, index: 0); |
309 | if (IS_ERR(ptr: lp->base_addr)) |
310 | return PTR_ERR(ptr: lp->base_addr); |
311 | |
312 | lp->irq = platform_get_irq(pdev, 0); |
313 | if (lp->irq < 0) |
314 | return lp->irq; |
315 | |
316 | rc = devm_request_irq(dev, irq: lp->irq, handler: &amd_axi_w1_irq, IRQF_TRIGGER_HIGH, DRIVER_NAME, dev_id: lp); |
317 | if (rc) |
318 | return rc; |
319 | |
320 | /* Initialize wait queue and flag */ |
321 | init_waitqueue_head(&lp->wait_queue); |
322 | |
323 | clk = devm_clk_get_enabled(dev, NULL); |
324 | if (IS_ERR(ptr: clk)) |
325 | return PTR_ERR(ptr: clk); |
326 | |
327 | /* Verify IP presence in HW */ |
328 | if (ioread32(lp->base_addr + AXIW1_IPID_REG) != AXIW1_IPID) { |
329 | dev_err(dev, "AMD 1-wire IP not detected in hardware\n" ); |
330 | return -ENODEV; |
331 | } |
332 | |
333 | /* |
334 | * Allow for future driver expansion supporting new hardware features |
335 | * This driver currently only supports hardware 1.x, but include logic |
336 | * to detect if a potentially incompatible future version is used |
337 | * by reading major version ID. It is highly undesirable for new IP versions |
338 | * to break the API, but this code will at least allow for graceful failure |
339 | * should that happen. Future new features can be enabled by hardware |
340 | * incrementing the minor version and augmenting the driver to detect capability |
341 | * using the minor version number |
342 | */ |
343 | val = ioread32(lp->base_addr + AXIW1_IPVER_REG); |
344 | ver_major = FIELD_GET(AXIW1_MAJORVER_MASK, val); |
345 | ver_minor = FIELD_GET(AXIW1_MINORVER_MASK, val); |
346 | |
347 | if (ver_major != 1) { |
348 | dev_err(dev, "AMD AXI W1 host version %u.%u is not supported by this driver" , |
349 | ver_major, ver_minor); |
350 | return -ENODEV; |
351 | } |
352 | |
353 | lp->bus_host.data = lp; |
354 | lp->bus_host.touch_bit = amd_axi_w1_touch_bit; |
355 | lp->bus_host.read_byte = amd_axi_w1_read_byte; |
356 | lp->bus_host.write_byte = amd_axi_w1_write_byte; |
357 | lp->bus_host.reset_bus = amd_axi_w1_reset_bus; |
358 | |
359 | amd_axi_w1_reset(amd_axi_w1_local: lp); |
360 | |
361 | platform_set_drvdata(pdev, data: lp); |
362 | rc = w1_add_master_device(master: &lp->bus_host); |
363 | if (rc) { |
364 | dev_err(dev, "Could not add host device\n" ); |
365 | return rc; |
366 | } |
367 | |
368 | return 0; |
369 | } |
370 | |
371 | static void amd_axi_w1_remove(struct platform_device *pdev) |
372 | { |
373 | struct amd_axi_w1_local *lp = platform_get_drvdata(pdev); |
374 | |
375 | w1_remove_master_device(master: &lp->bus_host); |
376 | } |
377 | |
378 | static const struct of_device_id amd_axi_w1_of_match[] = { |
379 | { .compatible = "amd,axi-1wire-host" }, |
380 | { /* end of list */ }, |
381 | }; |
382 | MODULE_DEVICE_TABLE(of, amd_axi_w1_of_match); |
383 | |
384 | static struct platform_driver amd_axi_w1_driver = { |
385 | .probe = amd_axi_w1_probe, |
386 | .remove_new = amd_axi_w1_remove, |
387 | .driver = { |
388 | .name = DRIVER_NAME, |
389 | .of_match_table = amd_axi_w1_of_match, |
390 | }, |
391 | }; |
392 | module_platform_driver(amd_axi_w1_driver); |
393 | |
394 | MODULE_LICENSE("GPL" ); |
395 | MODULE_AUTHOR("Kris Chaplin <kris.chaplin@amd.com>" ); |
396 | MODULE_DESCRIPTION("Driver for AMD AXI 1 Wire IP core" ); |
397 | |