blob: ac86dcf2ada062ed208f262f3bcfc8979025c4ab [file] [log] [blame]
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2009 Carl-Daniel Hailfinger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Uwe Hermann43959702010-03-13 17:28:29 +000014 */
15
16/*
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +000017 * Header file for hardware access and OS abstraction. Included from flash.h.
18 */
19
20#ifndef __HWACCESS_H__
21#define __HWACCESS_H__ 1
22
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000023#include "platform.h"
24
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +000025#if NEED_PCI == 1
Carl-Daniel Hailfinger72376832010-06-25 13:18:48 +000026/*
27 * libpci headers use the variable name "index" which triggers shadowing
28 * warnings on systems which have the index() function in a default #include
29 * or as builtin.
30 */
31#define index shadow_workaround_index
Stefan Taunerc65b8552013-09-12 15:48:39 +000032
Nico Huberc0e1c4b2022-12-13 21:55:22 +000033#if !defined (PCIUTILS_PCI_H)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +000034#include <pci/pci.h>
Stefan Taunerc65b8552013-09-12 15:48:39 +000035#else
36#include <pciutils/pci.h>
37#endif
38
Carl-Daniel Hailfinger72376832010-06-25 13:18:48 +000039#undef index
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000040#endif /* NEED_PCI == 1 */
41
Thomas Heijligencce1e5b2021-11-02 20:33:35 +010042void mmio_writeb(uint8_t val, void *addr);
43void mmio_writew(uint16_t val, void *addr);
44void mmio_writel(uint32_t val, void *addr);
45uint8_t mmio_readb(const void *addr);
46uint16_t mmio_readw(const void *addr);
47uint32_t mmio_readl(const void *addr);
48void mmio_readn(const void *addr, uint8_t *buf, size_t len);
49void mmio_le_writeb(uint8_t val, void *addr);
50void mmio_le_writew(uint16_t val, void *addr);
51void mmio_le_writel(uint32_t val, void *addr);
52uint8_t mmio_le_readb(const void *addr);
53uint16_t mmio_le_readw(const void *addr);
54uint32_t mmio_le_readl(const void *addr);
55#define pci_mmio_writeb mmio_le_writeb
56#define pci_mmio_writew mmio_le_writew
57#define pci_mmio_writel mmio_le_writel
58#define pci_mmio_readb mmio_le_readb
59#define pci_mmio_readw mmio_le_readw
60#define pci_mmio_readl mmio_le_readl
61void rmmio_writeb(uint8_t val, void *addr);
62void rmmio_writew(uint16_t val, void *addr);
63void rmmio_writel(uint32_t val, void *addr);
64void rmmio_le_writeb(uint8_t val, void *addr);
65void rmmio_le_writew(uint16_t val, void *addr);
66void rmmio_le_writel(uint32_t val, void *addr);
67#define pci_rmmio_writeb rmmio_le_writeb
68#define pci_rmmio_writew rmmio_le_writew
69#define pci_rmmio_writel rmmio_le_writel
70void rmmio_valb(void *addr);
71void rmmio_valw(void *addr);
72void rmmio_vall(void *addr);
73
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000074#define ___constant_swab8(x) ((uint8_t) ( \
75 (((uint8_t)(x) & (uint8_t)0xffU))))
76
77#define ___constant_swab16(x) ((uint16_t) ( \
78 (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
79 (((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
80
81#define ___constant_swab32(x) ((uint32_t) ( \
82 (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
83 (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
84 (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
85 (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
86
87#define ___constant_swab64(x) ((uint64_t) ( \
88 (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
89 (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
90 (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
91 (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
92 (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
93 (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
94 (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
95 (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56)))
96
97#if defined (__FLASHROM_BIG_ENDIAN__)
98
99#define cpu_to_le(bits) \
100static inline uint##bits##_t cpu_to_le##bits(uint##bits##_t val) \
101{ \
102 return ___constant_swab##bits(val); \
103}
104
105cpu_to_le(8)
106cpu_to_le(16)
107cpu_to_le(32)
108cpu_to_le(64)
109
110#define cpu_to_be8
111#define cpu_to_be16
112#define cpu_to_be32
113#define cpu_to_be64
114
115#elif defined (__FLASHROM_LITTLE_ENDIAN__)
116
117#define cpu_to_be(bits) \
118static inline uint##bits##_t cpu_to_be##bits(uint##bits##_t val) \
119{ \
120 return ___constant_swab##bits(val); \
121}
122
123cpu_to_be(8)
124cpu_to_be(16)
125cpu_to_be(32)
126cpu_to_be(64)
127
128#define cpu_to_le8
129#define cpu_to_le16
130#define cpu_to_le32
131#define cpu_to_le64
132
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000133#endif /* __FLASHROM_BIG_ENDIAN__ / __FLASHROM_LITTLE_ENDIAN__ */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000134
135#define be_to_cpu8 cpu_to_be8
136#define be_to_cpu16 cpu_to_be16
137#define be_to_cpu32 cpu_to_be32
138#define be_to_cpu64 cpu_to_be64
139#define le_to_cpu8 cpu_to_le8
140#define le_to_cpu16 cpu_to_le16
141#define le_to_cpu32 cpu_to_le32
142#define le_to_cpu64 cpu_to_le64
143
Carl-Daniel Hailfinger16c0aec2016-02-20 21:43:56 +0000144#if NEED_RAW_ACCESS == 1
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000145#if IS_X86
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000146
Gwenhael Goavec-Merou8cd0c732015-11-14 02:55:12 +0000147/* sys/io.h provides iopl(2) and x86 I/O port access functions (inb, outb etc).
148 * It is included in glibc (thus available also on debian/kFreeBSD) but also in other libcs that mimic glibc,
Stefan Tauner2c57bbe2016-02-20 20:21:58 +0000149 * e.g. musl and uclibc. Because we cannot detect the libc or existence of the header or of the instructions
150 * themselves safely in here we use some heuristic below:
151 * On Android we don't have the header file and no way for I/O port access at all. However, sys/glibc-syscalls.h
152 * refers to an iopl implementation and we therefore include at least that one for now. On non-Android we assume
153 * that a Linux system's libc has a suitable sys/io.h or (on non-Linux) we depend on glibc to offer it. */
154#if defined(__ANDROID__)
155#include <sys/glibc-syscalls.h>
156#elif defined(__linux__) || defined(__GLIBC__)
Gwenhael Goavec-Merou8cd0c732015-11-14 02:55:12 +0000157#include <sys/io.h>
158#endif
159
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000160#define __FLASHROM_HAVE_OUTB__ 1
161
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000162/* for iopl and outb under Solaris */
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000163#if defined (__sun)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000164#include <sys/sysi86.h>
165#include <sys/psw.h>
166#include <asm/sunddi.h>
167#endif
168
Carl-Daniel Hailfinger0d974e72010-07-17 12:54:09 +0000169/* Clarification about OUTB/OUTW/OUTL argument order:
170 * OUT[BWL](val, port)
171 */
172
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000173#if defined(__FreeBSD__) || defined(__DragonFly__)
Carl-Daniel Hailfingera5eecda2012-02-25 22:50:21 +0000174 /* Note that Debian/kFreeBSD (FreeBSD kernel with glibc) has conflicting
175 * out[bwl] definitions in machine/cpufunc.h and sys/io.h at least in some
176 * versions. Use machine/cpufunc.h only for plain FreeBSD/DragonFlyBSD.
177 */
Carl-Daniel Hailfinger16c0aec2016-02-20 21:43:56 +0000178 #include <sys/types.h>
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000179 #include <machine/cpufunc.h>
Michael Karchere7f32092010-01-12 15:36:24 +0000180 #define OUTB(x, y) do { u_int outb_tmp = (y); outb(outb_tmp, (x)); } while (0)
181 #define OUTW(x, y) do { u_int outw_tmp = (y); outw(outw_tmp, (x)); } while (0)
182 #define OUTL(x, y) do { u_int outl_tmp = (y); outl(outl_tmp, (x)); } while (0)
183 #define INB(x) __extension__ ({ u_int inb_tmp = (x); inb(inb_tmp); })
184 #define INW(x) __extension__ ({ u_int inw_tmp = (x); inw(inw_tmp); })
185 #define INL(x) __extension__ ({ u_int inl_tmp = (x); inl(inl_tmp); })
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000186#else
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000187
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000188#if defined (__sun)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000189 /* Note different order for outb */
190 #define OUTB(x,y) outb(y, x)
191 #define OUTW(x,y) outw(y, x)
192 #define OUTL(x,y) outl(y, x)
193 #define INB inb
194 #define INW inw
195 #define INL inl
196#else
Rudolf Marek03ae5c12010-03-16 23:59:19 +0000197
198#ifdef __DJGPP__
199
200#include <pc.h>
201
202 #define OUTB(x,y) outportb(y, x)
203 #define OUTW(x,y) outportw(y, x)
204 #define OUTL(x,y) outportl(y, x)
205
206 #define INB inportb
207 #define INW inportw
208 #define INL inportl
209
Uwe Hermann91f4afa2011-07-28 08:13:25 +0000210#else
Stefan Taunerc71759d2015-05-23 23:59:23 +0000211
212#if defined(__MACH__) && defined(__APPLE__)
213 /* Header is part of the DirectHW library. */
214 #include <DirectHW/DirectHW.h>
215#endif
216
Carl-Daniel Hailfingera5eecda2012-02-25 22:50:21 +0000217 /* This is the usual glibc interface. */
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000218 #define OUTB outb
219 #define OUTW outw
220 #define OUTL outl
221 #define INB inb
222 #define INW inw
223 #define INL inl
Rudolf Marek03ae5c12010-03-16 23:59:19 +0000224#endif
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000225#endif
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000226#endif
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000227
Carl-Daniel Hailfingerb63b0672010-07-02 17:12:50 +0000228#if defined(__NetBSD__) || defined (__OpenBSD__)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000229 #if defined(__i386__) || defined(__x86_64__)
230 #include <sys/types.h>
231 #include <machine/sysarch.h>
Stefan Tauner0554ca52013-07-25 22:54:25 +0000232 #if defined(__NetBSD__)
233 #if defined(__i386__)
234 #define iopl i386_iopl
235 #elif defined(__x86_64__)
236 #define iopl x86_64_iopl
237 #endif
238 #elif defined (__OpenBSD__)
239 #if defined(__i386__)
240 #define iopl i386_iopl
241 #elif defined(__amd64__)
242 #define iopl amd64_iopl
243 #endif
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000244 #endif
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000245
Uwe Hermann43959702010-03-13 17:28:29 +0000246static inline void outb(uint8_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000247{
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000248 __asm__ volatile ("outb %b0,%w1": :"a" (value), "Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000249}
250
Uwe Hermann43959702010-03-13 17:28:29 +0000251static inline uint8_t inb(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000252{
253 uint8_t value;
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000254 __asm__ volatile ("inb %w1,%0":"=a" (value):"Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000255 return value;
256}
257
Uwe Hermann43959702010-03-13 17:28:29 +0000258static inline void outw(uint16_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000259{
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000260 __asm__ volatile ("outw %w0,%w1": :"a" (value), "Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000261}
262
Uwe Hermann43959702010-03-13 17:28:29 +0000263static inline uint16_t inw(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000264{
265 uint16_t value;
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000266 __asm__ volatile ("inw %w1,%0":"=a" (value):"Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000267 return value;
268}
269
Uwe Hermann43959702010-03-13 17:28:29 +0000270static inline void outl(uint32_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000271{
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000272 __asm__ volatile ("outl %0,%w1": :"a" (value), "Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000273}
274
Uwe Hermann43959702010-03-13 17:28:29 +0000275static inline uint32_t inl(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000276{
277 uint32_t value;
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000278 __asm__ volatile ("inl %1,%0":"=a" (value):"Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000279 return value;
280}
281 #endif
282#endif
283
Carl-Daniel Hailfinger60d9bd22012-08-09 23:34:41 +0000284#if !(defined(__MACH__) && defined(__APPLE__)) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && !defined(__DragonFly__) && !defined(__LIBPAYLOAD__)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000285typedef struct { uint32_t hi, lo; } msr_t;
286msr_t rdmsr(int addr);
287int wrmsr(int addr, msr_t msr);
288#endif
Carl-Daniel Hailfingera5eecda2012-02-25 22:50:21 +0000289#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000290/* FreeBSD already has conflicting definitions for wrmsr/rdmsr. */
291#undef rdmsr
292#undef wrmsr
293#define rdmsr freebsd_rdmsr
294#define wrmsr freebsd_wrmsr
295typedef struct { uint32_t hi, lo; } msr_t;
296msr_t freebsd_rdmsr(int addr);
297int freebsd_wrmsr(int addr, msr_t msr);
298#endif
Patrick Georgia9095a92010-09-30 17:03:32 +0000299#if defined(__LIBPAYLOAD__)
300#include <arch/io.h>
301#include <arch/msr.h>
302typedef struct { uint32_t hi, lo; } msr_t;
303msr_t libpayload_rdmsr(int addr);
304int libpayload_wrmsr(int addr, msr_t msr);
305#undef rdmsr
306#define rdmsr libpayload_rdmsr
307#define wrmsr libpayload_wrmsr
308#endif
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000309
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000310#elif IS_PPC
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000311
312/* PCI port I/O is not yet implemented on PowerPC. */
313
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000314#elif IS_MIPS
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000315
316/* PCI port I/O is not yet implemented on MIPS. */
317
Stefan Taunerfb2d77c2015-02-10 08:03:10 +0000318#elif IS_SPARC
319
320/* PCI port I/O is not yet implemented on SPARC. */
321
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000322#elif IS_ARM
David Hendricksb286da72012-02-13 00:35:35 +0000323
324/* Non memory mapped I/O is not supported on ARM. */
325
Rosen Penev34d07f02019-07-02 00:14:01 -0700326#elif IS_ARC
327
328/* Non memory mapped I/O is not supported on ARC. */
329
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000330#else
331
332#error Unknown architecture, please check if it supports PCI port IO.
333
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000334#endif /* IS_* */
Carl-Daniel Hailfinger16c0aec2016-02-20 21:43:56 +0000335#endif /* NEED_RAW_ACCESS == 1 */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000336
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000337#endif /* !__HWACCESS_H__ */