1f21fb3edSRaghu Vatsavayi /**********************************************************************
2f21fb3edSRaghu Vatsavayi * Author: Cavium, Inc.
3f21fb3edSRaghu Vatsavayi *
4f21fb3edSRaghu Vatsavayi * Contact: support@cavium.com
5f21fb3edSRaghu Vatsavayi * Please include "LiquidIO" in the subject.
6f21fb3edSRaghu Vatsavayi *
750579d3dSRaghu Vatsavayi * Copyright (c) 2003-2016 Cavium, Inc.
8f21fb3edSRaghu Vatsavayi *
9f21fb3edSRaghu Vatsavayi * This file is free software; you can redistribute it and/or modify
10f21fb3edSRaghu Vatsavayi * it under the terms of the GNU General Public License, Version 2, as
11f21fb3edSRaghu Vatsavayi * published by the Free Software Foundation.
12f21fb3edSRaghu Vatsavayi *
13f21fb3edSRaghu Vatsavayi * This file is distributed in the hope that it will be useful, but
14f21fb3edSRaghu Vatsavayi * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
15f21fb3edSRaghu Vatsavayi * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
16f21fb3edSRaghu Vatsavayi * NONINFRINGEMENT. See the GNU General Public License for more
17f21fb3edSRaghu Vatsavayi * details.
18f21fb3edSRaghu Vatsavayi **********************************************************************/
19f21fb3edSRaghu Vatsavayi #include <linux/netdevice.h>
20f21fb3edSRaghu Vatsavayi #include "liquidio_common.h"
21f21fb3edSRaghu Vatsavayi #include "octeon_droq.h"
22f21fb3edSRaghu Vatsavayi #include "octeon_iq.h"
23f21fb3edSRaghu Vatsavayi #include "response_manager.h"
24f21fb3edSRaghu Vatsavayi #include "octeon_device.h"
2598cf1c67SWang Hai #include "octeon_mem_ops.h"
26f21fb3edSRaghu Vatsavayi
2715d3afccSFelix Manlunas #define MEMOPS_IDX BAR1_INDEX_DYNAMIC_MAP
28f21fb3edSRaghu Vatsavayi
29f21fb3edSRaghu Vatsavayi #ifdef __BIG_ENDIAN_BITFIELD
30a7d5a3dcSRaghu Vatsavayi static inline void
octeon_toggle_bar1_swapmode(struct octeon_device * oct,u32 idx)31a7d5a3dcSRaghu Vatsavayi octeon_toggle_bar1_swapmode(struct octeon_device *oct, u32 idx)
32a7d5a3dcSRaghu Vatsavayi {
33f21fb3edSRaghu Vatsavayi u32 mask;
34f21fb3edSRaghu Vatsavayi
35f21fb3edSRaghu Vatsavayi mask = oct->fn_list.bar1_idx_read(oct, idx);
36f21fb3edSRaghu Vatsavayi mask = (mask & 0x2) ? (mask & ~2) : (mask | 2);
37f21fb3edSRaghu Vatsavayi oct->fn_list.bar1_idx_write(oct, idx, mask);
38f21fb3edSRaghu Vatsavayi }
39a7d5a3dcSRaghu Vatsavayi #else
4097a25326SRaghu Vatsavayi #define octeon_toggle_bar1_swapmode(oct, idx)
41a7d5a3dcSRaghu Vatsavayi #endif
42f21fb3edSRaghu Vatsavayi
43f21fb3edSRaghu Vatsavayi static void
octeon_pci_fastwrite(struct octeon_device * oct,u8 __iomem * mapped_addr,u8 * hostbuf,u32 len)44f21fb3edSRaghu Vatsavayi octeon_pci_fastwrite(struct octeon_device *oct, u8 __iomem *mapped_addr,
45f21fb3edSRaghu Vatsavayi u8 *hostbuf, u32 len)
46f21fb3edSRaghu Vatsavayi {
47f21fb3edSRaghu Vatsavayi while ((len) && ((unsigned long)mapped_addr) & 7) {
48f21fb3edSRaghu Vatsavayi writeb(*(hostbuf++), mapped_addr++);
49f21fb3edSRaghu Vatsavayi len--;
50f21fb3edSRaghu Vatsavayi }
51f21fb3edSRaghu Vatsavayi
52f21fb3edSRaghu Vatsavayi octeon_toggle_bar1_swapmode(oct, MEMOPS_IDX);
53f21fb3edSRaghu Vatsavayi
54f21fb3edSRaghu Vatsavayi while (len >= 8) {
55f21fb3edSRaghu Vatsavayi writeq(*((u64 *)hostbuf), mapped_addr);
56f21fb3edSRaghu Vatsavayi mapped_addr += 8;
57f21fb3edSRaghu Vatsavayi hostbuf += 8;
58f21fb3edSRaghu Vatsavayi len -= 8;
59f21fb3edSRaghu Vatsavayi }
60f21fb3edSRaghu Vatsavayi
61f21fb3edSRaghu Vatsavayi octeon_toggle_bar1_swapmode(oct, MEMOPS_IDX);
62f21fb3edSRaghu Vatsavayi
63f21fb3edSRaghu Vatsavayi while (len--)
64f21fb3edSRaghu Vatsavayi writeb(*(hostbuf++), mapped_addr++);
65f21fb3edSRaghu Vatsavayi }
66f21fb3edSRaghu Vatsavayi
67f21fb3edSRaghu Vatsavayi static void
octeon_pci_fastread(struct octeon_device * oct,u8 __iomem * mapped_addr,u8 * hostbuf,u32 len)68f21fb3edSRaghu Vatsavayi octeon_pci_fastread(struct octeon_device *oct, u8 __iomem *mapped_addr,
69f21fb3edSRaghu Vatsavayi u8 *hostbuf, u32 len)
70f21fb3edSRaghu Vatsavayi {
71f21fb3edSRaghu Vatsavayi while ((len) && ((unsigned long)mapped_addr) & 7) {
72f21fb3edSRaghu Vatsavayi *(hostbuf++) = readb(mapped_addr++);
73f21fb3edSRaghu Vatsavayi len--;
74f21fb3edSRaghu Vatsavayi }
75f21fb3edSRaghu Vatsavayi
76f21fb3edSRaghu Vatsavayi octeon_toggle_bar1_swapmode(oct, MEMOPS_IDX);
77f21fb3edSRaghu Vatsavayi
78f21fb3edSRaghu Vatsavayi while (len >= 8) {
79f21fb3edSRaghu Vatsavayi *((u64 *)hostbuf) = readq(mapped_addr);
80f21fb3edSRaghu Vatsavayi mapped_addr += 8;
81f21fb3edSRaghu Vatsavayi hostbuf += 8;
82f21fb3edSRaghu Vatsavayi len -= 8;
83f21fb3edSRaghu Vatsavayi }
84f21fb3edSRaghu Vatsavayi
85f21fb3edSRaghu Vatsavayi octeon_toggle_bar1_swapmode(oct, MEMOPS_IDX);
86f21fb3edSRaghu Vatsavayi
87f21fb3edSRaghu Vatsavayi while (len--)
88f21fb3edSRaghu Vatsavayi *(hostbuf++) = readb(mapped_addr++);
89f21fb3edSRaghu Vatsavayi }
90f21fb3edSRaghu Vatsavayi
91f21fb3edSRaghu Vatsavayi /* Core mem read/write with temporary bar1 settings. */
92f21fb3edSRaghu Vatsavayi /* op = 1 to read, op = 0 to write. */
93f21fb3edSRaghu Vatsavayi static void
__octeon_pci_rw_core_mem(struct octeon_device * oct,u64 addr,u8 * hostbuf,u32 len,u32 op)94f21fb3edSRaghu Vatsavayi __octeon_pci_rw_core_mem(struct octeon_device *oct, u64 addr,
95f21fb3edSRaghu Vatsavayi u8 *hostbuf, u32 len, u32 op)
96f21fb3edSRaghu Vatsavayi {
97f21fb3edSRaghu Vatsavayi u32 copy_len = 0, index_reg_val = 0;
98f21fb3edSRaghu Vatsavayi unsigned long flags;
99f21fb3edSRaghu Vatsavayi u8 __iomem *mapped_addr;
10015d3afccSFelix Manlunas u64 static_mapping_base;
10115d3afccSFelix Manlunas
10215d3afccSFelix Manlunas static_mapping_base = oct->console_nb_info.dram_region_base;
10315d3afccSFelix Manlunas
10415d3afccSFelix Manlunas if (static_mapping_base &&
10515d3afccSFelix Manlunas static_mapping_base == (addr & ~(OCTEON_BAR1_ENTRY_SIZE - 1ULL))) {
10615d3afccSFelix Manlunas int bar1_index = oct->console_nb_info.bar1_index;
10715d3afccSFelix Manlunas
10815d3afccSFelix Manlunas mapped_addr = oct->mmio[1].hw_addr
10915d3afccSFelix Manlunas + (bar1_index << ilog2(OCTEON_BAR1_ENTRY_SIZE))
11015d3afccSFelix Manlunas + (addr & (OCTEON_BAR1_ENTRY_SIZE - 1ULL));
11115d3afccSFelix Manlunas
11215d3afccSFelix Manlunas if (op)
11315d3afccSFelix Manlunas octeon_pci_fastread(oct, mapped_addr, hostbuf, len);
11415d3afccSFelix Manlunas else
11515d3afccSFelix Manlunas octeon_pci_fastwrite(oct, mapped_addr, hostbuf, len);
11615d3afccSFelix Manlunas
11715d3afccSFelix Manlunas return;
11815d3afccSFelix Manlunas }
119f21fb3edSRaghu Vatsavayi
120f21fb3edSRaghu Vatsavayi spin_lock_irqsave(&oct->mem_access_lock, flags);
121f21fb3edSRaghu Vatsavayi
122f21fb3edSRaghu Vatsavayi /* Save the original index reg value. */
123f21fb3edSRaghu Vatsavayi index_reg_val = oct->fn_list.bar1_idx_read(oct, MEMOPS_IDX);
124f21fb3edSRaghu Vatsavayi do {
125f21fb3edSRaghu Vatsavayi oct->fn_list.bar1_idx_setup(oct, addr, MEMOPS_IDX, 1);
126f21fb3edSRaghu Vatsavayi mapped_addr = oct->mmio[1].hw_addr
127f21fb3edSRaghu Vatsavayi + (MEMOPS_IDX << 22) + (addr & 0x3fffff);
128f21fb3edSRaghu Vatsavayi
129f21fb3edSRaghu Vatsavayi /* If operation crosses a 4MB boundary, split the transfer
130f21fb3edSRaghu Vatsavayi * at the 4MB
131f21fb3edSRaghu Vatsavayi * boundary.
132f21fb3edSRaghu Vatsavayi */
133f21fb3edSRaghu Vatsavayi if (((addr + len - 1) & ~(0x3fffff)) != (addr & ~(0x3fffff))) {
134f21fb3edSRaghu Vatsavayi copy_len = (u32)(((addr & ~(0x3fffff)) +
135f21fb3edSRaghu Vatsavayi (MEMOPS_IDX << 22)) - addr);
136f21fb3edSRaghu Vatsavayi } else {
137f21fb3edSRaghu Vatsavayi copy_len = len;
138f21fb3edSRaghu Vatsavayi }
139f21fb3edSRaghu Vatsavayi
140f21fb3edSRaghu Vatsavayi if (op) { /* read from core */
141f21fb3edSRaghu Vatsavayi octeon_pci_fastread(oct, mapped_addr, hostbuf,
142f21fb3edSRaghu Vatsavayi copy_len);
143f21fb3edSRaghu Vatsavayi } else {
144f21fb3edSRaghu Vatsavayi octeon_pci_fastwrite(oct, mapped_addr, hostbuf,
145f21fb3edSRaghu Vatsavayi copy_len);
146f21fb3edSRaghu Vatsavayi }
147f21fb3edSRaghu Vatsavayi
148f21fb3edSRaghu Vatsavayi len -= copy_len;
149f21fb3edSRaghu Vatsavayi addr += copy_len;
150f21fb3edSRaghu Vatsavayi hostbuf += copy_len;
151f21fb3edSRaghu Vatsavayi
152f21fb3edSRaghu Vatsavayi } while (len);
153f21fb3edSRaghu Vatsavayi
154f21fb3edSRaghu Vatsavayi oct->fn_list.bar1_idx_write(oct, MEMOPS_IDX, index_reg_val);
155f21fb3edSRaghu Vatsavayi
156f21fb3edSRaghu Vatsavayi spin_unlock_irqrestore(&oct->mem_access_lock, flags);
157f21fb3edSRaghu Vatsavayi }
158f21fb3edSRaghu Vatsavayi
159f21fb3edSRaghu Vatsavayi void
octeon_pci_read_core_mem(struct octeon_device * oct,u64 coreaddr,u8 * buf,u32 len)160f21fb3edSRaghu Vatsavayi octeon_pci_read_core_mem(struct octeon_device *oct,
161f21fb3edSRaghu Vatsavayi u64 coreaddr,
162f21fb3edSRaghu Vatsavayi u8 *buf,
163f21fb3edSRaghu Vatsavayi u32 len)
164f21fb3edSRaghu Vatsavayi {
165f21fb3edSRaghu Vatsavayi __octeon_pci_rw_core_mem(oct, coreaddr, buf, len, 1);
166f21fb3edSRaghu Vatsavayi }
167*f71be9d0SMasahiro Yamada EXPORT_SYMBOL_GPL(octeon_pci_read_core_mem);
168f21fb3edSRaghu Vatsavayi
169f21fb3edSRaghu Vatsavayi void
octeon_pci_write_core_mem(struct octeon_device * oct,u64 coreaddr,const u8 * buf,u32 len)170f21fb3edSRaghu Vatsavayi octeon_pci_write_core_mem(struct octeon_device *oct,
171f21fb3edSRaghu Vatsavayi u64 coreaddr,
172b381f783SDenys Vlasenko const u8 *buf,
173f21fb3edSRaghu Vatsavayi u32 len)
174f21fb3edSRaghu Vatsavayi {
175b381f783SDenys Vlasenko __octeon_pci_rw_core_mem(oct, coreaddr, (u8 *)buf, len, 0);
176f21fb3edSRaghu Vatsavayi }
177*f71be9d0SMasahiro Yamada EXPORT_SYMBOL_GPL(octeon_pci_write_core_mem);
178f21fb3edSRaghu Vatsavayi
octeon_read_device_mem64(struct octeon_device * oct,u64 coreaddr)179f21fb3edSRaghu Vatsavayi u64 octeon_read_device_mem64(struct octeon_device *oct, u64 coreaddr)
180f21fb3edSRaghu Vatsavayi {
1815b173cf9SRaghu Vatsavayi __be64 ret;
182f21fb3edSRaghu Vatsavayi
183f21fb3edSRaghu Vatsavayi __octeon_pci_rw_core_mem(oct, coreaddr, (u8 *)&ret, 8, 1);
184f21fb3edSRaghu Vatsavayi
185f21fb3edSRaghu Vatsavayi return be64_to_cpu(ret);
186f21fb3edSRaghu Vatsavayi }
187*f71be9d0SMasahiro Yamada EXPORT_SYMBOL_GPL(octeon_read_device_mem64);
188f21fb3edSRaghu Vatsavayi
octeon_read_device_mem32(struct octeon_device * oct,u64 coreaddr)189f21fb3edSRaghu Vatsavayi u32 octeon_read_device_mem32(struct octeon_device *oct, u64 coreaddr)
190f21fb3edSRaghu Vatsavayi {
1915b173cf9SRaghu Vatsavayi __be32 ret;
192f21fb3edSRaghu Vatsavayi
193f21fb3edSRaghu Vatsavayi __octeon_pci_rw_core_mem(oct, coreaddr, (u8 *)&ret, 4, 1);
194f21fb3edSRaghu Vatsavayi
195f21fb3edSRaghu Vatsavayi return be32_to_cpu(ret);
196f21fb3edSRaghu Vatsavayi }
197*f71be9d0SMasahiro Yamada EXPORT_SYMBOL_GPL(octeon_read_device_mem32);
198f21fb3edSRaghu Vatsavayi
octeon_write_device_mem32(struct octeon_device * oct,u64 coreaddr,u32 val)199f21fb3edSRaghu Vatsavayi void octeon_write_device_mem32(struct octeon_device *oct, u64 coreaddr,
200f21fb3edSRaghu Vatsavayi u32 val)
201f21fb3edSRaghu Vatsavayi {
2025b173cf9SRaghu Vatsavayi __be32 t = cpu_to_be32(val);
203f21fb3edSRaghu Vatsavayi
204f21fb3edSRaghu Vatsavayi __octeon_pci_rw_core_mem(oct, coreaddr, (u8 *)&t, 4, 0);
205f21fb3edSRaghu Vatsavayi }
206*f71be9d0SMasahiro Yamada EXPORT_SYMBOL_GPL(octeon_write_device_mem32);
207