mediatek: add a new spi-nand driver for kernel 5.10
[openwrt/openwrt.git] / target / linux / mediatek / files-5.10 / drivers / mtd / mtk-snand / mtk-snand-os.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
4 *
5 * Author: Weijie Gao <weijie.gao@mediatek.com>
6 */
7
8 #ifndef _MTK_SNAND_OS_H_
9 #define _MTK_SNAND_OS_H_
10
11 #include <linux/slab.h>
12 #include <linux/kernel.h>
13 #include <linux/limits.h>
14 #include <linux/types.h>
15 #include <linux/bitops.h>
16 #include <linux/sizes.h>
17 #include <linux/iopoll.h>
18 #include <linux/hrtimer.h>
19 #include <linux/device.h>
20 #include <linux/dma-mapping.h>
21 #include <linux/io.h>
22 #include <asm/div64.h>
23
24 struct mtk_snand_plat_dev {
25 struct device *dev;
26 struct completion done;
27 };
28
29 /* Polling helpers */
30 #define read16_poll_timeout(addr, val, cond, sleep_us, timeout_us) \
31 readw_poll_timeout((addr), (val), (cond), (sleep_us), (timeout_us))
32
33 #define read32_poll_timeout(addr, val, cond, sleep_us, timeout_us) \
34 readl_poll_timeout((addr), (val), (cond), (sleep_us), (timeout_us))
35
36 /* Timer helpers */
37 #define mtk_snand_time_t ktime_t
38
39 static inline mtk_snand_time_t timer_get_ticks(void)
40 {
41 return ktime_get();
42 }
43
44 static inline mtk_snand_time_t timer_time_to_tick(uint32_t timeout_us)
45 {
46 return ktime_add_us(ktime_set(0, 0), timeout_us);
47 }
48
49 static inline bool timer_is_timeout(mtk_snand_time_t start_tick,
50 mtk_snand_time_t timeout_tick)
51 {
52 ktime_t tmo = ktime_add(start_tick, timeout_tick);
53
54 return ktime_compare(ktime_get(), tmo) > 0;
55 }
56
57 /* Memory helpers */
58 static inline void *generic_mem_alloc(struct mtk_snand_plat_dev *pdev,
59 size_t size)
60 {
61 return devm_kzalloc(pdev->dev, size, GFP_KERNEL);
62 }
63 static inline void generic_mem_free(struct mtk_snand_plat_dev *pdev, void *ptr)
64 {
65 devm_kfree(pdev->dev, ptr);
66 }
67
68 static inline void *dma_mem_alloc(struct mtk_snand_plat_dev *pdev, size_t size)
69 {
70 return kzalloc(size, GFP_KERNEL);
71 }
72 static inline void dma_mem_free(struct mtk_snand_plat_dev *pdev, void *ptr)
73 {
74 kfree(ptr);
75 }
76
77 static inline int dma_mem_map(struct mtk_snand_plat_dev *pdev, void *vaddr,
78 uintptr_t *dma_addr, size_t size, bool to_device)
79 {
80 dma_addr_t addr;
81 int ret;
82
83 addr = dma_map_single(pdev->dev, vaddr, size,
84 to_device ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
85 ret = dma_mapping_error(pdev->dev, addr);
86 if (ret)
87 return ret;
88
89 *dma_addr = (uintptr_t)addr;
90
91 return 0;
92 }
93
94 static inline void dma_mem_unmap(struct mtk_snand_plat_dev *pdev,
95 uintptr_t dma_addr, size_t size,
96 bool to_device)
97 {
98 dma_unmap_single(pdev->dev, dma_addr, size,
99 to_device ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
100 }
101
102 /* Interrupt helpers */
103 static inline void irq_completion_done(struct mtk_snand_plat_dev *pdev)
104 {
105 complete(&pdev->done);
106 }
107
108 static inline void irq_completion_init(struct mtk_snand_plat_dev *pdev)
109 {
110 init_completion(&pdev->done);
111 }
112
113 static inline int irq_completion_wait(struct mtk_snand_plat_dev *pdev,
114 void __iomem *reg, uint32_t bit,
115 uint32_t timeout_us)
116 {
117 int ret;
118
119 ret = wait_for_completion_timeout(&pdev->done,
120 usecs_to_jiffies(timeout_us));
121 if (!ret)
122 return -ETIMEDOUT;
123
124 return 0;
125 }
126
127 #endif /* _MTK_SNAND_OS_H_ */