97 Commits

Author SHA1 Message Date
Han Gao
62225503f5 configs: sync use ETNAVIV instead of Galcore
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-12-08 11:29:59 +08:00
Han Gao
dddd938847 config: ahead: enable bluetooth
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-12-08 11:28:26 +08:00
Robert Nelson
49c39d9e97 config: enable SERIAL_DEV_BUS/BT_HCIUART_BCM/BT_BCM
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-12-08 11:28:26 +08:00
Robert Nelson
918e660a58 cleanup: remove random BT_HCIUART_RTL3WIRE driver, sync back with v5.10.113
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-12-08 11:28:26 +08:00
Icenowy Zheng
b8c5d35460 revyos_defconfig: use ETNAVIV instead of Galcore
Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
2023-12-08 11:24:07 +08:00
Icenowy Zheng
afcdc418d4 drm/etnaviv: hack: use only pta id 0
Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
2023-12-08 11:24:07 +08:00
Icenowy Zheng
d6f09caa32 light: use etnaviv
Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
2023-12-08 11:24:07 +08:00
Icenowy Zheng
727e6f3be6 galcore: adapt to vivante,gc
Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
2023-12-08 11:24:07 +08:00
Icenowy Zheng
2f78e6b748 drm/etnaviv: add GC620
Dirty.

Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
2023-12-08 11:24:07 +08:00
Icenowy Zheng
cfe4413691 drm/etnaviv: add hwdb entry for TH1520 GC620
Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
2023-12-08 11:24:07 +08:00
Icenowy Zheng
373e8161c5 drm/etnaviv: add workaround for GC620 on TH1520 (0x5552)
Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
2023-12-08 11:24:07 +08:00
Icenowy Zheng
9ba56a64a8 drm/etnaviv: add handle for GPUs with only SECURITY_AHB flag
Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
2023-12-08 11:24:07 +08:00
Lucas Stach
ad542ee013 drm/etnaviv: expedited MMU fault handling
The GPU is halted when it hits a MMU exception, so there is no point in
waiting for the job timeout to expire or try to work out if the GPU is
still making progress in the timeout handler, as we know that the GPU
won't make any more progress.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com>
2023-12-08 11:24:07 +08:00
Lucas Stach
e44f708a9e drm/etnaviv: drop GPU initialized property
Now that it is only used to track the driver internal state of
the MMU global and cmdbuf objects, we can get rid of this property
by making the free/finit functions of those objects safe to call
on an uninitialized object.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com>
2023-12-08 11:24:07 +08:00
Lucas Stach
ccbbd8ae8f drm/etnaviv: better track GPU state
Instead of only tracking if the FE is running, use a enum to better
describe the various states the GPU can be in. This allows some
additional validation to make sure that functions that expect a
certain GPU state are only called when the GPU is actually in that
state.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com>
2023-12-08 11:24:07 +08:00
Lucas Stach
e286235a75 drm/etnaviv: avoid runtime PM usage in etnaviv_gpu_bind
Nothing in this callpath actually touches the GPU, so there is no reason
to get it out of suspend state here. Only if runtime PM isn't enabled at
all we must make sure to enable the clocks, so the GPU init routine can
access the GPU later on.

This also removes the need to guard against the state where the driver
isn't fully initialized yet in the runtime PM resume handler.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com>
2023-12-08 11:24:07 +08:00
Lucas Stach
e084b32587 drm/etnaviv: slow down FE idle polling
Currently the FE is spinning way too fast when polling for new work in
the FE idleloop. As each poll fetches 16 bytes from memory, a GPU running
at 1GHz with the current setting of 200 wait cycle between fetches causes
80 MB/s of memory traffic just to check for new work when the GPU is
otherwise idle, which is more FE traffic than in some GPU loaded cases.

Significantly increase the number of wait cycles to slow down the poll
interval to ~30µs, limiting the FE idle memory traffic to 512 KB/s, while
providing a max latency which should not hurt most use-cases. The FE WAIT
command seems to have some unknown discrete steps in the wait cycles so
we may over/undershoot the target a bit, but that should be harmless.

If the GPU core base frequency is unknown keep the 200 wait cycles as
a sane default.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Sui Jingfeng <suijingfeng@loongson.cn>
Tested-by: Sui Jingfeng <suijingfeng@loongson.cn>
Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com>
2023-12-08 11:24:07 +08:00
Lucas Stach
880ab177a1 drm/etnaviv: split fence lock
The fence lock currently protects two distinct things. It protects the fence
IDR from concurrent inserts and removes and also keeps drm_sched_job_arm and
drm_sched_entity_push_job in one atomic section to guarantee the fence seqno
monotonicity. Split the lock into those two functions.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
2023-12-08 11:24:07 +08:00
Christian Gmeiner
c32beb855f drm/etnaviv: print MMU exception cause
The MMU tells us the fault status. While the raw register value is
already printed, it's a bit more user friendly to translate the
fault reasons into human readable format.

Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
2023-12-08 11:24:07 +08:00
Lucas Stach
8304fb3b0e drm/etnaviv: switch to PFN mappings
There is no reason to use page based mappings, as the established
mappings are special driver mappings anyways and should not be
handled like normal pages.

Be consistent with what other drivers do and use raw PFN based
mappings.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2023-12-08 11:24:07 +08:00
Lucas Stach
51464f6592 drm/etnaviv: reap idle mapping if it doesn't match the softpin address
When a idle BO, which is held open by another process, gets freed by
userspace and subsequently referenced again by e.g. importing it again,
userspace may assign a different softpin VA than the last time around.
As the kernel GEM object still exists, we likely have a idle mapping
with the old VA still cached, if it hasn't been reaped in the meantime.

As the context matches, we then simply try to resurrect this mapping by
increasing the refcount. As the VA in this mapping does not match the
new softpin address, we consequently fail the otherwise valid submit.
Instead of failing, reap the idle mapping.

Cc: stable@vger.kernel.org # 5.19
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Guido Günther <agx@sigxcpu.org>
2023-12-08 11:24:07 +08:00
Lucas Stach
f87b29df53 drm/etnaviv: move idle mapping reaping into separate function
The same logic is already used in two different places and now
it will also be needed outside of the compilation unit, so split
it into a separate function.

Cc: stable@vger.kernel.org # 5.19
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Guido Günther <agx@sigxcpu.org>
2023-12-08 11:24:07 +08:00
Christian Gmeiner
c71d194901 drm/etnaviv: print offender task information on hangcheck recovery
Track the pid per submit, so we can print the name and cmdline of
the task which submitted the batch that caused the gpu to hang.

Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
2023-12-08 11:24:07 +08:00
Lucas Stach
dc96c0fe68 drm/etnaviv: reap idle softpin mappings when necessary
Right now the only point where softpin mappings get removed from the
MMU context is when the mapped GEM object is destroyed. However,
userspace might want to reuse that address space before the object
is destroyed, which is a valid usage, as long as all mapping in that
region of the address space are no longer used by any GPU jobs.

Implement reaping of idle MMU mappings that would otherwise
prevent the insertion of a softpin mapping.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Tested-by: Guido Günther <agx@sigxcpu.org>
Acked-by: Guido Günther <agx@sigxcpu.org>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
2023-12-08 11:24:07 +08:00
Lucas Stach
5ffd7f5029 drm/etnaviv: move flush_seq increment into etnaviv_iommu_map/unmap
The flush sequence is a marker that the page tables have been changed
and any affected TLBs need to be flushed. Move the flush_seq increment
a little further down the call stack to place it next to the actual
page table manipulation. Not functional change.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Tested-by: Guido Günther <agx@sigxcpu.org>
Acked-by: Guido Günther <agx@sigxcpu.org>
2023-12-08 11:24:07 +08:00
Lucas Stach
0f89c7db16 drm/etnaviv: move MMU context ref/unref into map/unmap_gem
This makes it a little more clear that the mapping holds a reference
to the context once the buffer has been successfully mapped into that
context and simplifies the error handling a bit.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Tested-by: Guido Günther <agx@sigxcpu.org>
Acked-by: Guido Günther <agx@sigxcpu.org>
2023-12-08 11:24:07 +08:00
Michael Walle
4a4a708db1 drm/etnaviv: use a 32 bit mask as coherent DMA mask
The STLB and the first command buffer (which is used to set up the TLBs)
has a 32 bit size restriction in hardware. There seems to be no way to
specify addresses larger than 32 bit. Keep it simple and restict the
addresses to the lower 4 GiB range for all coherent DMA memory
allocations.

Please note, that platform_device_alloc() will initialize dev->dma_mask
to point to pdev->platform_dma_mask, thus dma_set_mask() will work as
expected.

While at it, move the dma_mask setup code to the of_dma_configure() to
keep all the DMA setup code next to each other.

Suggested-by: Lucas Stach <l.stach@pengutronix.de>
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
2023-12-08 11:24:07 +08:00
Christian Gmeiner
255c988024 drm/etnaviv: provide more ID values via GET_PARAM ioctl.
Make it possible for the user space to access these ID values.

Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
2023-12-08 11:24:07 +08:00
Guido Günther
af2602ac87 drm/etnaviv: Add lockdep annotations for context lock
etnaviv_iommu_find_iova has it so etnaviv_iommu_insert_exact and
lockdep_assert_held should have it as well.

Signed-off-by: Guido Günther <agx@sigxcpu.org>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
2023-12-08 11:24:07 +08:00
Lucas Stach
b6d74c3560 drm/etnaviv: fix dumping of active MMU context
[ Upstream commit 20faf2005ec85fa1a6acc9a74ff27de667f90576 ]

gpu->mmu_context is the MMU context of the last job in the HW queue, which
isn't necessarily the same as the context from the bad job. Dump the MMU
context from the scheduler determined bad submit to make it work as intended.

Fixes: 17e4660ae3d7 ("drm/etnaviv: implement per-process address spaces on MMUv2")
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2023-12-08 11:24:07 +08:00
Lucas Stach
8f3347a598 drm/etnaviv: fix reference leak when mmaping imported buffer
commit 963b2e8c428f79489ceeb058e8314554ec9cbe6f upstream.

drm_gem_prime_mmap() takes a reference on the GEM object, but before that
drm_gem_mmap_obj() already takes a reference, which will be leaked as only
one reference is dropped when the mapping is closed. Drop the extra
reference when dma_buf_mmap() succeeds.

Cc: stable@vger.kernel.org
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2023-12-08 11:24:07 +08:00
Lucas Stach
9aa4002cc9 drm/etnaviv: don't truncate physical page address
[ Upstream commit d37c120b73128690434cc093952439eef9d56af1 ]

While the interface for the MMU mapping takes phys_addr_t to hold a
full 64bit address when necessary and MMUv2 is able to map physical
addresses with up to 40bit, etnaviv_iommu_map() truncates the address
to 32bits. Fix this by using the correct type.

Fixes: 931e97f3afd8 ("drm/etnaviv: mmuv2: support 40 bit phys address")
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2023-12-08 11:24:07 +08:00
Doug Brown
e025348004 drm/etnaviv: add missing quirks for GC300
[ Upstream commit cc7d3fb446a91f24978a6aa59cbb578f92e22242 ]

The GC300's features register doesn't specify that a 2D pipe is
available, and like the GC600, its idle register reports zero bits where
modules aren't present.

Signed-off-by: Doug Brown <doug@schmorgal.com>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2023-12-08 11:24:07 +08:00
Lucas Stach
58f804da14 drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
commit e168c25526cd0368af098095c2ded4a008007e1b upstream.

When the mapping is already reaped the unmap must be a no-op, as we
would otherwise try to remove the mapping twice, corrupting the involved
data structures.

Cc: stable@vger.kernel.org # 5.4
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Tested-by: Guido Günther <agx@sigxcpu.org>
Acked-by: Guido Günther <agx@sigxcpu.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2023-12-08 11:24:07 +08:00
Thomas Zimmermann
277f5bc2bc drm/etnaviv: Introduce GEM object functions
GEM object functions deprecate several similar callback interfaces in
struct drm_driver. This patch replaces the per-driver callbacks with
per-instance callbacks in etnaviv. The only exception is gem_prime_mmap,
which is non-trivial to convert.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Acked-by: Lucas Stach <l.stach@pengutronix.de>
Acked-by: Christian König <christian.koenig@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200923102159.24084-4-tzimmermann@suse.de
2023-12-08 11:24:07 +08:00
Lucas Stach
2dc08a7dac drm/etnaviv: rework linear window offset calculation
The current calculation based on the required_dma mask can be significantly
off, so that the linear window only overlaps a small part of the DRAM
address space. This can lead to the command buffer being unmappable, which
is obviously bad.

Rework the linear window offset calculation to be based on the command buffer
physical address, making sure that the command buffer is always mappable.

Tested-by: Primoz Fiser <primoz.fiser@norik.com>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
2023-12-08 11:24:07 +08:00
Icenowy Zheng
05735e9ff4 drm/verisilicon: fix cursor position
The cursor should be placed at (x + hot_x, y + hot_y) to allow partial
display of a cursor.

Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
2023-12-05 23:38:42 +08:00
Han Gao
d81a2398a8 nf: enable nf mangle
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-12-03 15:33:55 +08:00
Han Gao
e133903e4d meles: add 4g/8g dts
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-12-03 14:53:53 +08:00
Han Gao
8b4bca072c meles: fix: usb2.0
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-12-03 14:53:53 +08:00
Haaland Chen
026ae08e53 riscv: dts: light: add Milk-V Meles board
Signed-off-by: Haaland Chen <haaland@milkv.io>
2023-12-03 14:53:53 +08:00
Han Gao
95a545985b riscv: default enable xtheadc
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-11-29 23:46:21 +08:00
Han Gao
f722795a38 toolchains: fix mainline toolchain build
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-11-29 23:46:21 +08:00
Han Gao
06bd593cfd ci: kernel auto build on thead-gcc & mainline-gcc
thead-gcc: v2.8.0
mainline-gcc: v13.2

Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-11-29 23:46:21 +08:00
Jisheng Zhang
556f057aca riscv: cmpxchg: implement arch_cmpxchg64_{relaxed|acquire|release}
After selecting ARCH_USE_CMPXCHG_LOCKREF, one straight futher
optimization is implementing the arch_cmpxchg64_relaxed() because the
lockref code does not need the cmpxchg to have barrier semantics. At
the same time, implement arch_cmpxchg64_acquire and
arch_cmpxchg64_release as well.

However, on both TH1520 and JH7110 platforms, I didn't see obvious
performance improvement with Linus' test case [1]. IMHO, this may
be related with the fence and lr.d/sc.d hw implementations. In theory,
lr/sc without fence could give performance improvement over lr/sc plus
fence, so add the code here to leave performance improvement room on
newer HW platforms.

Link: http://marc.info/?l=linux-fsdevel&m=137782380714721&w=4 [1]
Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
2023-11-29 23:46:21 +08:00
Jisheng Zhang
186355454e riscv: select ARCH_USE_CMPXCHG_LOCKREF
Select ARCH_USE_CMPXCHG_LOCKREF to enable the cmpxchg-based lockless lockref
implementation for riscv.

Using Linus' test case[1] on TH1520 platform, I see a 11.2% improvement.
On JH7110 platform, I see 12.0% improvement.

Link: http://marc.info/?l=linux-fsdevel&m=137782380714721&w=4 [1]
Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
2023-11-29 23:46:21 +08:00
Jisheng Zhang
b25b9b6b16 riscv: select ARCH_HAS_FAST_MULTIPLIER
Currently, riscv linux requires at least IMA, so all platforms have a
multiplier. And I assume the 'mul' efficiency is comparable or better
than a sequence of five or so register-dependent arithmetic
instructions. Select ARCH_HAS_FAST_MULTIPLIER to get slightly nicer
codegen. Refer to commit f9b4192923fa ("[PATCH] bitops: hweight()
speedup") for more details.

In a simple benchmark test calling hweight64() in a loop, it got:
about 14% preformance improvement on JH7110, tested on Milkv Mars.

about 23% performance improvement on TH1520 and SG2042, tested on
Sipeed LPI4A and SG2042 platform.

a slight performance drop on CV1800B, tested on milkv duo. Among all
riscv platforms in my hands, this is the only one which sees a slight
performance drop. It means the 'mul' isn't quick enough. However, the
situation exists on x86 too, for example, P4 doesn't have fast
integer multiplies as said in the above commit, x86 also selects
ARCH_HAS_FAST_MULTIPLIER. So let's select ARCH_HAS_FAST_MULTIPLIER
which can benefit almost riscv platforms.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Tested-by: Samuel Holland <samuel.holland@sifive.com>
2023-11-29 23:46:21 +08:00
Icenowy Zheng
35a32afaf8 Kernel: fix out-of-tree build for merged kernel modules
Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
2023-11-29 12:54:48 +08:00
NekoRouter
3e042d29a3 Re-disable pwm,qspi0,qspi1 on beagle board
Keep light-a and beagle both can work
2023-10-22 21:04:53 -05:00
NekoRouter
c32ad7b836 Revert "sync: device-tree changes from main repo"
Enable pwm, qspi0, qspi1 on all devices

This reverts partial of commit 40ef3b0976
2023-10-22 21:04:53 -05:00
NekoRouter
99a459c9f7 Add MIPI panel driver, MIPI panel and touch controller Kconfig, New devicetree file 2023-10-22 21:04:53 -05:00
Han Gao
c10fdb081d feat: update npu-ax3386 with sdk1.2.1
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-10-18 22:16:33 +08:00
Han Gao
e3b22dbe54 ci: use revyos_beaglev_defconfig for ahead & cleanup
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-10-10 14:46:45 -05:00
Han Gao
b9526ccc12 config: use separate revyos_beaglev_defconfig
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-10-10 14:46:45 -05:00
Han Gao
f05fed4b3a Revert "fix: temporarily turn off Bluetooth build for ahead"
Use separate config

This reverts commit fe82c45483.
2023-10-10 14:46:45 -05:00
Han Gao
3e8db613d4 fix: reduce log level for aic8800
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-10-10 13:38:16 -05:00
Lu Hui
e04af8ab30 revyos_defconfig: enable aic8800 wifi 2023-10-10 13:38:16 -05:00
Lu Hui
a29e54cb02 drivers: wireless: add aic8800 support 2023-10-10 13:38:16 -05:00
Han Gao
fe82c45483 fix: temporarily turn off Bluetooth build for ahead
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-10-10 16:24:12 +08:00
Han Gao
c64537c234 fix: fix ftbfs for openwrt
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-10-09 15:46:44 -05:00
Han Gao
e0b5c2d836 Revert "Fix DSI"
This reverts commit c37f2020a7fe989eedec6edfc30c6ff1888a1bcf.
2023-10-09 15:46:44 -05:00
Han Gao
65d28e339c chore: force CONFIG_LOCALVERSION_AUTO=n
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-10-09 15:46:44 -05:00
Han Gao
383394d925 chore: sync revyos_config for sdk 1.2.0
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-10-09 15:46:44 -05:00
Han Gao
76d072714b fix: sync beagle devicetree
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-10-09 15:46:44 -05:00
Han Gao
f107c010f0 chore: sync revyos_config
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-10-09 15:46:44 -05:00
Robert Nelson
21488b4bba BeagleV: remove uart4 configuration and leave it to u-boot
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Robert Nelson
4090089096 NFM: quiet: hub usb usb2-port1
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Deepak Khatri
48d0bea232 Fix DSI 2023-10-09 15:46:44 -05:00
Deepak Khatri
0f0b0abd92 Free up P8.12 2023-10-09 15:46:44 -05:00
Deepak Khatri
2864ff8827 Free up P8.08 & P8.09 2023-10-09 15:46:44 -05:00
Robert Nelson
3b1e9db0d7 Make sure to build overlays
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Robert Nelson
d7048c221b BeagleV: add overlays
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Robert Nelson
d92a0f15a5 config: switch from /usr/lib/ -> /lib/ for wifi
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Robert Nelson
e4706a16f3 sync: Fix gpio pins input issue
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Robert Nelson
34157258d7 dt: merge in BlueTooth pinmux changes
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Robert Nelson
825f6a577e dt: sync MB_CS
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Robert Nelson
f0fba63d97 merge: dt: add cape header pins
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Robert Nelson
790c65208f light-beagle-ref.dts: rename board
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Robert Nelson
4f4ed3f042 light-beagle: disable mipi, then hdmi just works
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Robert Nelson
4d4f6ba338 ToolChain: switch to something we can download with wget
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Robert Nelson
40ef3b0976 sync: device-tree changes from main repo
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Robert Nelson
921113dc1d config: sync config
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Robert Nelson
296d3dc80c config: enable a suite of generic drivers
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Robert Nelson
d592c8d305 config: sync filesystem options
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Robert Nelson
8d34c4a386 config: SECURITY profile
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:46:44 -05:00
Robert Nelson
2360026a43 config: enable MODULE_COMPRESS_XZ
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:39:45 -05:00
Robert Nelson
dd0b44d681 config: sync debian networking stack
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:39:45 -05:00
Robert Nelson
3366ec3f14 config: enable leds support
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:39:45 -05:00
Robert Nelson
c2bb75e485 riscv: support Overlay Buildling
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:39:45 -05:00
Han Gao
a854067698 chore: remove compress
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-10-09 15:33:03 -05:00
Han Gao
580ea36ab7 chore: add ci for ahead
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-10-09 15:33:03 -05:00
Robert Nelson
2fac2fed77 config: add our default gadget loading configuration
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:33:03 -05:00
Robert Nelson
ac080f0f32 config: add docker.io defaults
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:33:03 -05:00
Robert Nelson
22994ee8fd config: disable CONFIG_DEBUG_INFO/CONFIG_RUNTIME_TESTING_MENU
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:33:03 -05:00
Robert Nelson
dd5c99c459 Add_Eth_Phy_and_Wifi_Ble_driver_for_BeagleV_board
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:33:03 -05:00
Robert Nelson
798c6e25dc BeagleV: copy light_defconfig as beaglev_defconfig
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
2023-10-09 15:33:03 -05:00
Han Gao
ed4a257bd1 fix: cluster mask reg_usb_hub_vcc5v gpio
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2023-10-10 03:20:28 +08:00
495 changed files with 518277 additions and 6061 deletions

View File

@@ -8,25 +8,29 @@ on:
- cron: "0 2 * * *"
env:
xuetie_toolchain: https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1663142514282
toolchain_file_name: Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.6.1-20220906.tar.gz
xuantie_toolchain: https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1698113812618
toolchain_file_name: Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.8.0-20231018.tar.gz
mainline_toolchain: https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/2023.10.18
mainline_toolchain_file_name: riscv64-glibc-ubuntu-22.04-gcc-nightly-2023.10.18-nightly.tar.gz
wget_alias: 'wget --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 -t 0'
ARCH: riscv
board: lpi4a
KBUILD_BUILD_USER: builder
KBUILD_BUILD_HOST: revyos-riscv-builder
KDEB_COMPRESS: xz
KDEB_CHANGELOG_DIST: unstable
jobs:
kernel:
strategy:
fail-fast: false
matrix:
include:
- name: thead-gcc
toolchain_tripe: riscv64-unknown-linux-gnu-
- name: gcc-12
toolchain_tripe: riscv64-linux-gnu-
name: [thead-gcc, gcc-13]
board: [lpi4a, ahead]
runs-on: ubuntu-22.04
env:
CROSS_COMPILE: ${{ matrix.toolchain_tripe }}
CROSS_COMPILE: riscv64-unknown-linux-gnu-
steps:
- name: Install software
@@ -36,68 +40,50 @@ jobs:
libncurses-dev gawk flex bison openssl libssl-dev tree \
dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf device-tree-compiler \
devscripts
sudo update-alternatives --install \
/usr/bin/riscv64-linux-gnu-gcc riscv64-gcc /usr/bin/riscv64-linux-gnu-gcc-12 10
sudo update-alternatives --install \
/usr/bin/riscv64-linux-gnu-g++ riscv64-g++ /usr/bin/riscv64-linux-gnu-g++-12 10
- name: Checkout kernel
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
path: 'kernel'
- name: Configure toolchains
run: |
mkdir rootfs && mkdir rootfs/boot
if [ x"${{ matrix.name }}" = x"thead-gcc" ]; then
wget ${xuetie_toolchain}/${toolchain_file_name}
tar -xvf ${toolchain_file_name} -C /opt
fi
- name: Compile Kernel && Install
run: |
export PATH="/opt/Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.6.1/bin:$PATH"
mkdir -p rootfs
if [[ ${{ matrix.name }} = "thead-gcc" ]]; then
${wget_alias} ${xuantie_toolchain}/${toolchain_file_name}
tar -xvf ${toolchain_file_name} -C /opt
export PATH="/opt/Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.8.0/bin:$PATH"
else
${wget_alias} ${mainline_toolchain}/${mainline_toolchain_file_name}
tar -xvf ${mainline_toolchain_file_name} -C /opt
export PATH="/opt/riscv/bin:$PATH"
fi
${CROSS_COMPILE}gcc -v
pushd kernel
make revyos_defconfig
export KDEB_PKGVERSION="$(date "+%Y.%m.%d.%H.%M")+$(git rev-parse --short HEAD)"
if [ x"${{ matrix.name }}" = x"gcc-12" ]; then
echo "CONFIG_THEAD_ISA=n" >> .config
elif [ x"${{ matrix.name }}" = x"thead-gcc" ]; then
echo "CONFIG_THEAD_ISA=y" >> .config
if [ x"${{ matrix.board }}" = x"lpi4a" ]; then
make revyos_defconfig
elif [ x"${{ matrix.board }}" = x"ahead" ]; then
make revyos_beaglev_defconfig
fi
make -j$(nproc) bindeb-pkg LOCALVERSION="-${board}"
make -j$(nproc) dtbs
# if [ x"$(cat .config | grep CONFIG_MODULES=y)" = x"CONFIG_MODULES=y" ]; then
# sudo make INSTALL_MOD_PATH=${GITHUB_WORKSPACE}/rootfs/ modules_install -j$(nproc)
# fi
# sudo make INSTALL_PATH=${GITHUB_WORKSPACE}/rootfs/boot install -j$(nproc)
export KDEB_PKGVERSION="$(date "+%Y.%m.%d.%H.%M")+$(git rev-parse --short HEAD)"
sed -i '/CONFIG_LOCALVERSION_AUTO/d' .config && echo "CONFIG_LOCALVERSION_AUTO=n" >> .config
cat .config | grep "CONFIG_THEAD_ISA"
make -j$(nproc) bindeb-pkg LOCALVERSION="-${{ matrix.board }}"
# Copy deb
sudo dcmd cp -v ../*.changes ${GITHUB_WORKSPACE}/rootfs/
# build perf & install
# make LDFLAGS=-static NO_LIBELF=1 NO_JVMTI=1 VF=1 -C tools/perf/
# sudo mkdir -p ${GITHUB_WORKSPACE}/rootfs/sbin/
# sudo cp -v tools/perf/perf ${GITHUB_WORKSPACE}/rootfs/sbin/perf-thead
# Install Kernel
# sudo cp -v arch/riscv/boot/Image ${GITHUB_WORKSPACE}/rootfs/boot/
# record commit-id
git rev-parse HEAD > kernel-commitid
sudo cp -v kernel-commitid ${GITHUB_WORKSPACE}/rootfs/boot/
git rev-parse HEAD > ${{ matrix.board }}-kernel-commitid
sudo cp -v ${{ matrix.board }}-kernel-commitid ${GITHUB_WORKSPACE}/rootfs/
# Install DTB
sudo cp -v arch/riscv/boot/dts/thead/{light-lpi4a.dtb,light-lpi4a-16gb.dtb} ${GITHUB_WORKSPACE}/rootfs/boot/
ls -al ${GITHUB_WORKSPACE}/rootfs/
popd
- name: compress
run: tar -zcvf thead-kernel-${{ matrix.name }}.tar.gz rootfs
- name: 'Upload Artifact'
uses: actions/upload-artifact@v3
with:
name: thead-kernel-${{ matrix.name }}.tar.gz
path: thead-kernel-${{ matrix.name }}.tar.gz
name: thead-kernel-${{ matrix.name }}
path: rootfs/*
retention-days: 30

1
.gitignore vendored
View File

@@ -18,6 +18,7 @@
*.c.[012]*.*
*.dt.yaml
*.dtb
*.dtbo
*.dtb.S
*.dwo
*.elf

View File

@@ -18,6 +18,7 @@ config RISCV
select ARCH_HAS_DEBUG_VM_PGTABLE
select ARCH_HAS_DEBUG_VIRTUAL if MMU
select ARCH_HAS_DEBUG_WX
select ARCH_HAS_FAST_MULTIPLIER
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_GIGANTIC_PAGE
select ARCH_HAS_KCOV
@@ -34,6 +35,7 @@ config RISCV
select ARCH_KEEP_MEMBLOCK
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT
select ARCH_USE_CMPXCHG_LOCKREF
select ARCH_USE_QUEUED_SPINLOCKS
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
@@ -403,7 +405,9 @@ config VECTOR
config THEAD_ISA
bool "T-HEAD extension ISA in AFLAGS with -march=_xtheadc"
default n
default y
help
Say N here if you want to disable xtheadc in the kernel.
endmenu

View File

@@ -50,10 +50,15 @@ endif
# ISA string setting
riscv-march-$(CONFIG_ARCH_RV32I) := rv32ima
riscv-march-$(CONFIG_ARCH_RV64I) := rv64ima
riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd
riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd
riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c
riscv-march-$(CONFIG_VECTOR) := $(riscv-march-y)v0p7
riscv-march-$(CONFIG_THEAD_ISA) := $(riscv-march-y)_xtheadc
# Fix mainline build
toolchain-have-v0p7 := $(call cc-option-yn, -march=$(riscv-march-y)v0p7)
riscv-march-$(toolchain-have-v0p7) := $(riscv-march-y)v0p7
toolchain-have-xtheadc := $(call cc-option-yn, -march=$(riscv-march-y)_xtheadc)
riscv-march-$(toolchain-have-xtheadc) := $(riscv-march-y)_xtheadc
# Newer binutils versions default to ISA spec version 20191213 which moves some
# instructions from the I extension to the Zicsr and Zifencei extensions.

View File

@@ -1,4 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
ifeq ($(CONFIG_OF_OVERLAY),y)
DTC_FLAGS += -@
endif
subdir-y += sifive
subdir-y += kendryte
subdir-y += thead

View File

@@ -1,4 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
ifeq ($(CONFIG_OF_OVERLAY),y)
DTC_FLAGS += -@
endif
dtb-$(CONFIG_SOC_THEAD) += ice.dtb
dtb-$(CONFIG_SOC_THEAD) += light-fm-emu.dtb light_mpw.dtb
dtb-$(CONFIG_SOC_THEAD) += light-fm-emu-npu-fce.dtb
@@ -29,7 +34,7 @@ dtb-$(CONFIG_SOC_THEAD) += light-a-val-full.dtb
dtb-$(CONFIG_SOC_THEAD) += light-ant-ref.dtb
dtb-$(CONFIG_SOC_THEAD) += light-ant-discrete.dtb
dtb-$(CONFIG_SOC_THEAD) += light-beagle.dtb
dtb-$(CONFIG_SOC_THEAD) += light-lpi4a.dtb light-lpi4a-ddr2G.dtb light-lpi4a-16gb.dtb
dtb-$(CONFIG_SOC_THEAD) += light-lpi4a.dtb light-lpi4a-ddr2G.dtb light-lpi4a-16gb.dtb light-lpi4a-dsi0-hdmi.dtb
dtb-$(CONFIG_SOC_THEAD) += light-lpi4a-cluster.dtb light-lpi4a-cluster-16gb.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-ref.dtb light-a-ref-dsi0.dtb light-a-ref-dsi0-hdmi.dtb
dtb-$(CONFIG_SOC_THEAD) += light-b-ref.dtb
@@ -42,3 +47,9 @@ dtb-$(CONFIG_SOC_THEAD) += fire-emu.dtb fire-emu-crash.dtb
dtb-$(CONFIG_SOC_THEAD) += fire-emu-soc-base.dtb fire-emu-soc-c910x4.dtb fire-emu-gpu-dpu-dsi0.dtb fire-emu-vi-dsp-vo.dtb fire-emu-vi-vp-vo.dtb
dtb-$(CONFIG_SOC_THEAD) += fire-emu-soc-base-sec.dtb
dtb-$(CONFIG_SOC_THEAD) += light-lpi4a-laptop.dtb
dtb-$(CONFIG_SOC_THEAD) += light-milkv-meles.dtb light-milkv-meles-4g.dtb
targets += dtbs dtbs_install
targets += $(dtb-y)
subdir-y := overlays

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2021 Alibaba Group Holding Limited.
* Copyright (C) 2022 BeagleBoard.org - https://beagleboard.org/
* Copyright (C) 2022 Deepak Khatri <lorforlinux@beagleboard.org>
*/
/dts-v1/;
@@ -10,13 +12,8 @@
#include <dt-bindings/gpio/gpio.h>
#include "light-vi-devices.dtsi"
/ {
model = "T-HEAD Light val board";
compatible = "thead,light-val", "thead,light";
memory@0 {
device_type = "memory";
reg = <0x0 0x200000 0x0 0x7fe00000>;
};
model = "BeagleBoard.org BeagleV-Ahead";
compatible = "beagle,light", "thead,light-val", "thead,light";
chosen {
bootargs = "console=ttyS0,115200 crashkernel=256M-:128M earlycon clk_ignore_unused sram=0xffe0000000,0x180000";
@@ -25,11 +22,42 @@
leds {
compatible = "gpio-leds";
status = "disabled";
led0 {
label = "SYS_STATUS";
gpios = <&gpio1_porta 15 0>; /* GPIO_ACTIVE_HIGH: 0 */
default-state = "off";
pinctrl-names = "default";
pinctrl-0 = <&led_pins_default>;
led-0 {
label = "beaglebone:green:usr0";
gpios = <&ao_gpio4_porta 8 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
//function = LED_FUNCTION_HEARTBEAT;
};
led-1 {
label = "beaglebone:green:usr1";
gpios = <&ao_gpio4_porta 9 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "mmc0";
//function = LED_FUNCTION_DISK_ACTIVITY;
};
led-2 {
label = "beaglebone:green:usr2";
gpios = <&ao_gpio4_porta 10 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "cpu";
//function = LED_FUNCTION_CPU;
};
led-3 {
label = "beaglebone:green:usr3";
gpios = <&ao_gpio4_porta 11 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "mmc1";
//function = LED_FUNCTION_DISK_ACTIVITY;
};
led-4 {
label = "beaglebone:green:usr4";
gpios = <&ao_gpio4_porta 12 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "netdev";
//function = LED_FUNCTION_WLAN;
};
};
@@ -194,10 +222,9 @@
};
dummy_codec: dummy_codec {
#sound-dai-cells = <0>;
compatible = "thead,light-dummy-pcm";
#sound-dai-cells = <1>;
compatible = "linux,bt-sco";
status = "okay";
sound-name-prefix = "DUMMY";
};
reg_vref_1v8: regulator-adc-verf {
@@ -205,56 +232,9 @@
regulator-name = "vref-1v8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
status = "okay";
};
reg_tp_pwr_en: regulator-pwr-en {
compatible = "regulator-fixed";
regulator-name = "PWR_EN";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
gpio = <&gpio1_porta 12 1>;
enable-active-high;
regulator-always-on;
};
wcn_wifi: wireless-wlan {
compatible = "wlan-platdata";
clock-names = "clk_wifi";
ref-clock-frequency = <24000000>;
keep_wifi_power_on;
pinctrl-names = "default";
wifi_chip_type = "rtl8723ds";
WIFI,poweren_gpio = <&gpio2_porta 29 0>;
WIFI,reset_n = <&gpio2_porta 22 0>;
status = "okay";
};
wcn_bt: wireless-bluetooth {
compatible = "bluetooth-platdata";
pinctrl-names = "default", "rts_gpio";
BT,power_gpio = <&gpio2_porta 29 0>;
status = "okay";
};
gpio-keys {
compatible = "gpio-keys";
pinctrl-0 = <&pinctrl_volume>;
pinctrl-names = "default";
key-volumedown {
label = "Volume Down Key";
linux,code = <KEY_VOLUMEDOWN>;
debounce-interval = <1>;
gpios = <&gpio1_porta 19 0x1>;
};
key-volumeup {
label = "Volume Up Key";
linux,code = <KEY_VOLUMEUP>;
debounce-interval = <1>;
gpios = <&gpio2_porta 25 0x1>;
};
};
aon: aon {
compatible = "thead,light-aon";
mbox-names = "aon";
@@ -286,119 +266,6 @@
regulator-always-on;
};
soc_vdd_3v3_en_reg: soc_vdd_3v3_en {
compatible = "regulator-fixed";
regulator-name = "soc_vdd_3v3_en";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio0_porta 30 1>;
enable-active-high;
regulator-always-on;
};
soc_lcd0_bias_en_reg: soc_lcd0_bias_en {
compatible = "regulator-fixed";
regulator-name = "soc_lcd0_bias_en";
regulator-min-microvolt = <5700000>;
regulator-max-microvolt = <5700000>;
gpio = <&gpio1_porta 10 1>;
enable-active-high;
};
soc_vdd18_lcd0_en_reg: soc_lcd0_en {
compatible = "regulator-fixed";
regulator-name = "soc_lcd0_en";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
gpio = <&gpio1_porta 9 1>;
enable-active-high;
};
soc_vdd5v_se_en_reg: soc_vdd5v_se_en {
compatible = "regulator-fixed";
regulator-name = "soc_vdd5v_se_en";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio2_porta 14 1>;
enable-active-high;
regulator-always-on;
};
soc_wcn33_en_reg: soc_wcn33_en {
compatible = "regulator-fixed";
regulator-name = "soc_wcn33_en";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio2_porta 29 1>;
enable-active-high;
regulator-always-on;
};
soc_vbus_en_reg: soc_vbus_en {
compatible = "regulator-fixed";
regulator-name = "soc_vbus_en";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio2_porta 28 1>;
enable-active-high;
regulator-always-on;
};
soc_avdd28_rgb_reg: soc_avdd28_rgb {
compatible = "regulator-fixed";
regulator-name = "soc_avdd28_rgb";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
gpio = <&gpio1_porta 15 1>;
enable-active-high;
};
soc_dovdd18_rgb_reg: soc_dovdd18_rgb {
compatible = "regulator-fixed";
regulator-name = "soc_dovdd18_rgb";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
gpio = <&gpio1_porta 13 1>;
enable-active-high;
};
soc_dvdd12_rgb_reg: soc_dvdd12_rgb {
compatible = "regulator-fixed";
regulator-name = "soc_dvdd12_rgb";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
gpio = <&gpio1_porta 14 1>;
enable-active-high;
};
soc_avdd25_ir_reg: soc_avdd25_ir {
compatible = "regulator-fixed";
regulator-name = "soc_avdd25_ir";
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <2500000>;
gpio = <&gpio0_porta 28 1>;
enable-active-high;
};
soc_dovdd18_ir_reg: soc_dovdd18_ir {
compatible = "regulator-fixed";
regulator-name = "soc_dovdd18_ir";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
gpio = <&gpio1_porta 13 1>;
enable-active-high;
};
soc_dvdd12_ir_reg: soc_dvdd12_ir {
compatible = "regulator-fixed";
regulator-name = "soc_dvdd12_ir";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
gpio = <&gpio0_porta 29 1>;
enable-active-high;
};
aon_reg_dialog: light-dialog-reg {
compatible = "thead,light-dialog-pmic-ant";
status = "okay";
@@ -620,10 +487,11 @@
w25q,fast-read;
};
spidev@1 {
compatible = "spidev";
channel@1 {
compatible = "rohm,dh2228fv";
//symlink = "bone/spi/0.1";
#address-cells = <0x1>;
#size-cells = <0x1>;
#size-cells = <0x0>;
reg = <0x1>;
spi-max-frequency = <50000000>;
};
@@ -659,10 +527,11 @@
compatible = "snps,dw-apb-ssi";
num-cs = <1>;
cs-gpios = <&gpio0_porta 1 0>;
status = "okay";
status = "disabled";
spidev@0 {
compatible = "spidev";
channel@0 {
compatible = "rohm,dh2228fv";
//symlink = "bone/spi/1.1";
#address-cells = <0x1>;
#size-cells = <0x1>;
reg = <0x0>;
@@ -740,7 +609,7 @@
};
&padctrl0_apsys { /* right-pinctrl */
light-evb-padctrl0 {
light_padctrl0: light-evb-padctrl0 {
/*
* Pin Configuration Node:
* Format: <pin_id mux_node config>
@@ -789,12 +658,20 @@
thead,pins = <
FM_GPIO3_2 0x1 0x208 /* pwm0 */
>;
};
};
pinctrl_bt: btgrp {
thead,pins = <
FM_SDIO1_WPRTN 0x3 0x72
FM_SDIO1_DETN 0x3 0x72
FM_GPIO2_30 0x0 0x72
>;
};
};
};
&padctrl1_apsys { /* left-pinctrl */
light-evb-padctrl1 {
light_padctrl1: light-evb-padctrl1 {
/*
* Pin Configuration Node:
* Format: <pin_id mux_node config>
@@ -833,18 +710,24 @@
FM_QSPI1_D2_WP 0x1 0x238
FM_QSPI1_D3_HOLD 0x1 0x238
>;
};
pinctrl_volume: volume_grp {
thead,pins = <
FM_CLK_OUT_2 0x3 0x208
>;
};
};
};
};
/*
PIN , 0x0, 0x1, 0x2, 0x3, 0x4, 0x5
AUDIO_PA8, AUDIO_PA8, NULL, NULL, GPIO4_8, NULL, NULL
AUDIO_PA9, AUDIO_PA9, NULL, NULL, GPIO4_9, NULL, NULL
AUDIO_PA10, AUDIO_PA10, NULL, NULL, GPIO4_10, NULL, NULL
AUDIO_PA11, AUDIO_PA11, NULL, NULL, GPIO4_11, NULL, NULL
AUDIO_PA12, AUDIO_PA12, NULL, NULL, GPIO4_12, NULL, NULL
*/
#define FM_AUDIO_PA8_AUDIO_PA8 0x00
#define FM_AUDIO_PA8_GPIO 0x03
&padctrl_aosys {
light-aon-padctrl {
light_padctrl: light-aon-padctrl {
/*
* Pin Configuration Node:
* Format: <pin_id mux_node config>
@@ -862,12 +745,26 @@
>;
};
led_pins_default: leds0_grp {
thead,pins = <
FM_AUDIO_PA8 0x3 0x72
FM_AUDIO_PA9 0x3 0x72
FM_AUDIO_PA10 0x3 0x72
FM_AUDIO_PA11 0x3 0x72
FM_AUDIO_PA12 0x3 0x72
>;
};
};
};
&i2c0 {
clock-frequency = <400000>;
status = "okay";
eeprom@50 {
compatible = "atmel,24c32";
reg = <0x50>;
};
};
&i2c1 {
@@ -953,85 +850,6 @@
memory-region = <&dsp1_mem>;
};
&vvcam_flash_led0{
flash_led_name = "aw36413_aw36515";
floodlight_i2c_bus = /bits/ 8 <2>;
floodlight_en_pin = <&gpio1_porta 26 0>;
projection_i2c_bus = /bits/ 8 <1>;
flash_led_touch_pin = <&gpio1_porta 27 0>; //flash led touch pin
io-channels = <&adc 2>;
io-channel-names = "projection_adc";
status = "okay";
};
&vvcam_sensor0 {
sensor_name = "SC2310";
sensor_regulators = "DOVDD18_RGB", "DVDD12_RGB", "AVDD28_RGB";
sensor_regulator_timing_us = <70 50 20>;
sensor_pdn = <&gpio1_porta 21 0>; //powerdown pin / shutdown pin
sensor_rst = <&gpio1_porta 16 0>;
sensor_pdn_delay_us = <4000>; //powerdown pin / shutdown pin actived till I2C ready
DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>;
DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>;
AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>;
i2c_reg_width = /bits/ 8 <2>;
i2c_data_width = /bits/ 8 <1>;
i2c_addr = /bits/ 8 <0x30>;
i2c_bus = /bits/ 8 <3>;
status = "okay";
};
&vvcam_sensor1 {
sensor_name = "SC132GS";
sensor_regulators = "DOVDD18_IR", "DVDD12_IR", "AVDD25_IR";
sensor_regulator_timing_us = <70 1000 2000>;
i2c_addr = /bits/ 8 <0x31>;
sensor_pdn = <&gpio1_porta 28 0>; //powerdown pin / shutdown pin
sensor_rst = <&gpio1_porta 24 0>;
sensor_pdn_delay_us = <2000>; //powerdown pin / shutdown pin actived till I2C ready
DOVDD18_IR-supply = <&soc_dovdd18_ir_reg>;
DVDD12_IR-supply = <&soc_dvdd12_ir_reg>;
AVDD25_IR-supply = <&soc_avdd25_ir_reg>;
i2c_reg_width = /bits/ 8 <2>;
i2c_data_width = /bits/ 8 <1>;
i2c_bus = /bits/ 8 <2>;
status = "okay";
};
&vvcam_sensor2 {
sensor_name = "GC5035";
sensor_regulators = "DOVDD18_SCAN", "DVDD12_SCAN", "AVDD28_SCAN";
sensor_regulator_timing_us = <100 50 0>;
sensor_pdn = <&gpio1_porta 30 0>; //powerdown pin / shutdown pin
sensor_rst = <&gpio1_porta 29 0>;
sensor_pdn_delay_us = <1000>; //powerdown pin / shutdown pin actived till I2C ready
DOVDD18_SCAN-supply = <&soc_dovdd18_scan_reg>;
DVDD12_SCAN-supply = <&soc_dvdd12_scan_reg>;
AVDD28_SCAN-supply = <&soc_avdd28_scan_en_reg>;
i2c_addr = /bits/ 8 <0x37>;
i2c_bus = /bits/ 8 <4>;
i2c_reg_width = /bits/ 8 <1>;
i2c_data_width = /bits/ 8 <1>;
status = "okay";
};
&vvcam_sensor3 {
sensor_name = "GC02M1B";
sensor_regulators = "DOVDD18_SCAN", "DVDD12_SCAN", "AVDD28_SCAN";
sensor_regulator_timing_us = <100 50 0>;
sensor_pdn = <&gpio1_porta 30 0>; //powerdown pin / shutdown pin
sensor_rst = <&gpio1_porta 29 0>;
sensor_pdn_delay_us = <1000>; //powerdown pin / shutdown pin actived till I2C ready
DOVDD18_SCAN-supply = <&soc_dovdd18_scan_reg>;
DVDD12_SCAN-supply = <&soc_dvdd12_scan_reg>;
AVDD28_SCAN-supply = <&soc_avdd28_scan_en_reg>;
i2c_addr = /bits/ 8 <0x37>;
i2c_bus = /bits/ 8 <4>;
i2c_reg_width = /bits/ 8 <1>;
i2c_data_width = /bits/ 8 <1>;
status = "okay";
};
&video0{
vi_mem_pool_region = <2>; // vi_mem: framebuffer, region[2]
channel0 {
@@ -2179,21 +1997,6 @@
status = "okay";
};
&dpu_enc0 {
status = "okay";
ports {
/* output */
port@1 {
reg = <1>;
enc0_out: endpoint {
remote-endpoint = <&dsi0_in>;
};
};
};
};
&dpu_enc1 {
ports {
/delete-node/ port@0;
@@ -2204,46 +2007,6 @@
status = "okay";
};
&dsi0 {
status = "okay";
};
&dhost_0 {
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dsi0_in: endpoint {
remote-endpoint = <&enc0_out>;
};
};
port@1 {
reg = <1>;
dsi0_out: endpoint {
remote-endpoint = <&panel0_in>;
};
};
};
panel0@0 {
compatible = "i2c_dsi,ili9881d";
reg = <0>;
mcu_auto_reset_enable = <0>;
tp_point_rotate = <0>;
port {
panel0_in: endpoint {
remote-endpoint = <&dsi0_out>;
};
};
};
};
&disp1_out {
remote-endpoint = <&hdmi_tx_in>;
};
@@ -2261,11 +2024,6 @@
&lightsound {
status = "okay";
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"Speaker", "AW87519 VO",
"AW87519 IN", "ES8156 ROUT";
simple-audio-card,aux-devs = <&audio_aw87519_pa>;
simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>;
format = "i2s";
@@ -2293,13 +2051,13 @@
sound-dai = <&light_i2s 1>;
};
codec {
sound-dai = <&dummy_codec>;
sound-dai = <&dummy_codec 2>;
};
};
};
&light_i2s {
status = "okay";
status = "disabled";
};
&i2s0 {
@@ -2321,12 +2079,14 @@
300000 650000
800000 700000
1500000 800000
1848000 1000000
>;
light,dvddm-operating-points = <
/* kHz uV */
300000 800000
800000 800000
1500000 800000
1848000 1000000
>;
};
c910_1: cpu@1 {
@@ -2335,12 +2095,14 @@
300000 650000
800000 700000
1500000 800000
1848000 1000000
>;
light,dvddm-operating-points = <
/* kHz uV */
300000 800000
800000 800000
1500000 800000
1848000 1000000
>;
};
c910_2: cpu@2 {
@@ -2350,12 +2112,14 @@
300000 650000
800000 700000
1500000 800000
1848000 1000000
>;
light,dvddm-operating-points = <
/* kHz uV */
300000 800000
800000 800000
1500000 800000
1848000 1000000
>;
};
c910_3: cpu@3 {
@@ -2365,12 +2129,14 @@
300000 650000
800000 700000
1500000 800000
1848000 1000000
>;
light,dvddm-operating-points = <
/* kHz uV */
300000 800000
800000 800000
1500000 800000
1848000 1000000
>;
};
};

View File

@@ -7,6 +7,27 @@
#include "light-beagle-ref.dts"
/ {
bcmdhd_wlan {
compatible = "android,bcmdhd_wlan";
gpio_wl_reg_on = <&gpio2_porta 31 1>;
gpio_wl_host_wake = <&gpio2_porta 25 1>;
};
};
&pwm {
status = "disabled";
};
&qspi0 {
status = "disabled";
};
&qspi1 {
status = "disabled";
};
&vvcam_sensor4 { // beagle board J5 CSI0 connector
sensor_name = "IMX219";
sensor_pdn = <&gpio2_porta 23 0>; //powerdown pin / shutdown pin
@@ -703,3 +724,5 @@ video12: tuningtool
};
};
};
#include "light-beagle-bone-buses.dtsi"

View File

@@ -24,3 +24,7 @@
&reg_usb_hub_vdd1v2 {
/delete-property/ gpio;
};
&reg_usb_hub_vcc5v {
/delete-property/ gpio;
};

View File

@@ -24,3 +24,7 @@
&reg_usb_hub_vdd1v2 {
/delete-property/ gpio;
};
&reg_usb_hub_vcc5v {
/delete-property/ gpio;
};

View File

@@ -0,0 +1,131 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2022 Alibaba Group Holding Limited.
*/
#include "light-lpi4a-ref.dts"
/ {
model = "T-HEAD Light Lichee Pi 4A configuration for 8GB DDR board";
compatible = "thead,light-val", "thead,light-lpi4a", "thead,light";
memory@0 {
device_type = "memory";
reg = <0x0 0x00000000 0x2 0x00000000>;
};
};
&cmamem {
alloc-ranges = <0x1 0xe4000000 0 0x14000000>; // [0x1E400_0000 ~ 0x1F800_0000]
};
&pwm {
status = "okay";
};
&qspi0 {
status = "okay";
};
&qspi1 {
status = "okay";
};
&i2c3 {
touch@14 {
#gpio-cells = <2>;
compatible = "goodix,gt9271";
reg = <0x14>;
interrupt-parent = <&ao_gpio_porta>;
interrupts = <3 0>;
irq-gpios = <&ao_gpio_porta 3 0>;
reset-gpios = <&pcal6408ahk_d 0 0>;
AVDD28-supply = <&reg_tp_pwr_en>;
touchscreen-size-x = <800>;
touchscreen-size-y = <1280>;
tp-size = <9271>;
status = "okay";
};
};
&dpu_enc0 {
status = "okay";
ports {
/* output */
port@1 {
reg = <1>;
enc0_out: endpoint {
remote-endpoint = <&dsi0_in>;
};
};
};
};
&dpu_enc1 {
ports {
/delete-node/ port@0;
};
};
&dpu {
status = "okay";
};
&dsi0 {
status = "okay";
};
&dhost_0 {
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dsi0_in: endpoint {
remote-endpoint = <&enc0_out>;
};
};
port@1 {
reg = <1>;
dsi0_out: endpoint {
remote-endpoint = <&panel0_in>;
};
};
};
panel0@0 {
compatible = "chongzhou,cz101b4001", "jadard,jd9365da-h3";
reg = <0>;
backlight = <&lcd0_backlight>;
reset-gpio = <&pcal6408ahk_d 7 0>; /* active low */
hsvcc-supply = <&soc_vdd18_lcd0_en_reg>;
vspn3v3-supply = <&soc_vdd33_lcd0_en_reg>;
port {
panel0_in: endpoint {
remote-endpoint = <&dsi0_out>;
};
};
};
};
&disp1_out {
remote-endpoint = <&hdmi_tx_in>;
};
&hdmi_tx {
status = "okay";
port@0 {
/* input */
hdmi_tx_in: endpoint {
remote-endpoint = <&disp1_out>;
};
};
};

View File

@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2022 Alibaba Group Holding Limited.
*/
#include "light-milkv-meles.dts"
/ {
model = "Milk-V Meles 4G";
compatible = "milkv,meles", "thead,light";
memory@0 {
device_type = "memory";
reg = <0x0 0x200000 0x0 0xffe00000>;
};
};

View File

@@ -0,0 +1,885 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2021-2022 Alibaba Group Holding Limited.
*/
/dts-v1/;
#include "light.dtsi"
#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
/ {
model = "Milk-V Meles";
compatible = "milkv,meles", "thead,light";
aliases {
mmc0 = &emmc;
mmc1 = &sdhci0;
mmc2 = &sdhci1;
};
chosen {
bootargs = "console=ttyS0,115200 crashkernel=256M-:128M earlycon clk_ignore_unused sram=0xffe0000000,0x180000";
stdout-path = "serial0:115200n8";
};
memory@0 {
device_type = "memory";
reg = <0x0 0x200000 0x1 0xffe00000>;
};
display_subsystem: display-subsystem {
status = "okay";
};
leds {
compatible = "gpio-leds";
led0 {
label = "SYS_STATUS";
gpios = <&gpio1_porta 15 0>; /* GPIO_ACTIVE_HIGH: 0 */
default-state = "off";
};
led1 {
label = "USER_LED";
gpios = <&gpio1_porta 16 0>; /* GPIO_ACTIVE_HIGH: 0 */
linux,default-trigger = "heartbeat";
default-state = "on";
};
};
light_iopmp: iopmp {
compatible = "thead,light-iopmp";
/* config#1: multiple valid regions */
iopmp_emmc: IOPMP_EMMC {
regions = <0x000000 0x100000>,
<0x100000 0x200000>;
attr = <0xFFFFFFFF>;
dummy_slave= <0x800000>;
};
/* config#2: iopmp bypass */
iopmp_sdio0: IOPMP_SDIO0 {
bypass_en;
};
/* config#3: iopmp default region set */
iopmp_sdio1: IOPMP_SDIO1 {
attr = <0xFFFFFFFF>;
is_default_region;
};
iopmp_usb0: IOPMP_USB0 {
attr = <0xFFFFFFFF>;
is_default_region;
};
iopmp_ao: IOPMP_AO {
is_default_region;
};
iopmp_aud: IOPMP_AUD {
is_default_region;
};
iopmp_chip_dbg: IOPMP_CHIP_DBG {
is_default_region;
};
iopmp_eip120i: IOPMP_EIP120I {
is_default_region;
};
iopmp_eip120ii: IOPMP_EIP120II {
is_default_region;
};
iopmp_eip120iii: IOPMP_EIP120III {
is_default_region;
};
iopmp_isp0: IOPMP_ISP0 {
is_default_region;
};
iopmp_isp1: IOPMP_ISP1 {
is_default_region;
};
iopmp_dw200: IOPMP_DW200 {
is_default_region;
};
iopmp_vipre: IOPMP_VIPRE {
is_default_region;
};
iopmp_venc: IOPMP_VENC {
is_default_region;
};
iopmp_vdec: IOPMP_VDEC {
is_default_region;
};
iopmp_g2d: IOPMP_G2D {
is_default_region;
};
iopmp_fce: IOPMP_FCE {
is_default_region;
};
iopmp_npu: IOPMP_NPU {
is_default_region;
};
iopmp0_dpu: IOPMP0_DPU {
bypass_en;
};
iopmp1_dpu: IOPMP1_DPU {
bypass_en;
};
iopmp_gpu: IOPMP_GPU {
is_default_region;
};
iopmp_gmac1: IOPMP_GMAC1 {
is_default_region;
};
iopmp_gmac2: IOPMP_GMAC2 {
is_default_region;
};
iopmp_dmac: IOPMP_DMAC {
is_default_region;
};
iopmp_tee_dmac: IOPMP_TEE_DMAC {
is_default_region;
};
iopmp_dsp0: IOPMP_DSP0 {
is_default_region;
};
iopmp_dsp1: IOPMP_DSP1 {
is_default_region;
};
};
mbox_910t_client1: mbox_910t_client1 {
compatible = "thead,light-mbox-client";
mbox-names = "902";
mboxes = <&mbox_910t 1 0>;
status = "disabled";
};
mbox_910t_client2: mbox_910t_client2 {
compatible = "thead,light-mbox-client";
mbox-names = "906";
mboxes = <&mbox_910t 2 0>;
status = "disabled";
};
lightsound: lightsound@1 {
status = "okay";
compatible = "simple-audio-card";
simple-audio-card,name = "Light-Sound-Card";
#address-cells = <1>;
#size-cells = <0>;
/* I2S - AUDIO SYS CODEC 8156*/
simple-audio-card,dai-link@0 {
reg = <0>;
format = "i2s";
cpu {
sound-dai = <&i2s1 0>;
};
codec {
sound-dai = <&es8156_audio_codec>;
};
};
/* I2S - HDMI */
simple-audio-card,dai-link@1 {
reg = <1>;
format = "i2s";
cpu {
sound-dai = <&light_i2s 1>;
};
codec {
sound-dai = <&dummy_codec>;
};
};
};
wifi_pwrseq: wifi-pwrseq {
status = "okay";
compatible = "mmc-pwrseq-simple";
reset-gpios = <&gpio0_porta 20 1>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_wireless_power>;
};
dummy_codec: dummy_codec {
#sound-dai-cells = <0>;
compatible = "thead,light-dummy-pcm";
status = "okay";
sound-name-prefix = "DUMMY";
};
vdd_5v: regulator-vdd-5v {
compatible = "regulator-fixed";
regulator-name = "vdd_5v";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-boot-on;
regulator-always-on;
status = "okay";
};
vdd_1v8: regulator-vdd-1v8 {
compatible = "regulator-fixed";
regulator-name = "vdd_1v8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
vin-supply = <&vdd_5v>;
status = "okay";
};
reg_vref_1v8: regulator-adc-verf {
compatible = "regulator-fixed";
regulator-name = "vref-1v8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
status = "okay";
};
vcc_usb_en: regulator-usb-en {
compatible = "regulator-fixed";
regulator-name = "vcc_usb_en";
gpio = <&gpio2_porta 30 1>; /* GPIO_ACTIVE_LOW: 1 */
regulator-boot-on;
regulator-always-on;
status = "okay";
};
aon {
compatible = "thead,light-aon";
mbox-names = "aon";
mboxes = <&mbox_910t 1 0>;
status = "okay";
pd: light-aon-pd {
compatible = "thead,light-aon-pd";
#power-domain-cells = <1>;
};
aon_reg_dialog: light-dialog-reg {
compatible = "thead,light-dialog-pmic-ant";
status = "okay";
dvdd_cpu_reg: appcpu_dvdd {
regulator-name = "appcpu_dvdd";
regulator-min-microvolt = <300000>;
regulator-max-microvolt = <1570000>;
regulator-boot-on;
regulator-always-on;
};
dvddm_cpu_reg: appcpu_dvddm {
regulator-name = "appcpu_dvddm";
regulator-min-microvolt = <300000>;
regulator-max-microvolt = <1570000>;
regulator-boot-on;
regulator-always-on;
};
soc_dvdd18_aon_reg: soc_dvdd18_aon {
regulator-name = "soc_dvdd18_aon";
regulator-boot-on;
regulator-always-on;
};
soc_avdd33_usb3_reg: soc_avdd33_usb3 {
regulator-name = "soc_avdd33_usb3";
regulator-boot-on;
regulator-always-on;
};
soc_dvdd08_aon_reg: soc_dvdd08_aon {
regulator-name = "soc_dvdd08_aon";
regulator-boot-on;
regulator-always-on;
};
soc_dvdd08_ddr_reg: soc_dvdd08_ddr {
regulator-name = "soc_dvdd08_ddr";
regulator-boot-on;
regulator-always-on;
};
soc_vdd_ddr_1v8_reg: soc_vdd_ddr_1v8 {
regulator-name = "soc_vdd_ddr_1v8";
regulator-boot-on;
regulator-always-on;
};
soc_vdd_ddr_1v1_reg: soc_vdd_ddr_1v1 {
regulator-name = "soc_vdd_ddr_1v1";
regulator-boot-on;
regulator-always-on;
};
soc_vdd_ddr_0v6_reg: soc_vdd_ddr_0v6 {
regulator-name = "soc_vdd_ddr_0v6";
regulator-boot-on;
regulator-always-on;
};
soc_dvdd18_ap_reg: soc_dvdd18_ap {
regulator-name = "soc_dvdd18_ap";
regulator-boot-on;
regulator-always-on;
};
soc_avdd08_mipi_hdmi_reg: soc_avdd08_mipi_hdmi {
regulator-name = "soc_avdd08_mipi_hdmi";
regulator-boot-on;
regulator-always-on;
};
soc_avdd18_mipi_hdmi_reg: soc_avdd18_mipi_hdmi {
regulator-name = "soc_avdd18_mipi_hdmi";
regulator-boot-on;
regulator-always-on;
};
soc_vdd33_emmc_reg: soc_vdd33_emmc {
regulator-name = "soc_vdd33_emmc";
regulator-boot-on;
regulator-always-on;
};
soc_vdd18_emmc_reg: soc_vdd18_emmc {
regulator-name = "soc_vdd18_emmc";
regulator-boot-on;
regulator-always-on;
};
soc_dovdd18_scan_reg: soc_dovdd18_scan {
regulator-name = "soc_dovdd18_scan";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
};
soc_dvdd12_scan_reg: soc_dvdd12_scan {
regulator-name = "soc_dvdd12_scan";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <3600000>;
};
soc_avdd28_scan_en_reg: soc_avdd28_scan_en {
regulator-name = "soc_avdd28_scan_en";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <3600000>;
};
};
c910_cpufreq {
compatible = "thead,light-mpw-cpufreq";
status = "okay";
};
test: light-aon-test {
compatible = "thead,light-aon-test";
};
};
};
&cmamem {
alloc-ranges = <0 0xe4000000 0 0x14000000>; // [0xE400_0000 ~ 0xF800_0000]
};
&resmem {
#address-cells = <2>;
#size-cells = <2>;
ranges;
tee_mem: memory@1a000000 {
reg = <0x0 0x1a000000 0 0x4000000>;
no-map;
};
dsp0_mem: memory@20000000 { /**0x2000_0000~0x2040_0000 4M**/
reg = <0x0 0x20000000 0x0 0x00280000 /* DSP FW code&data section 2.5M*/
0x0 0x20280000 0x0 0x00001000 /* DSP communication area 4K*/
0x0 0x20281000 0x0 0x00007000 /* Panic/log page 28K */
0x0 0x20288000 0x0 0x00178000>; /* DSP shared memory 1.5M-32K*/
no-map;
};
dsp1_mem: memory@20400000 { /**0x2040_0000~0x2080_0000 4M**/
reg = <0x0 0x20400000 0x0 0x00280000 /* DSP FW code&data section */
0x0 0x20680000 0x0 0x00001000 /* DSP communication area */
0x0 0x20681000 0x0 0x00007000 /* Panic/log page*/
0x0 0x20688000 0x0 0x00178000>; /* DSP shared memory */
no-map;
};
vi_mem: framebuffer@0f800000 {
reg = <0x0 0x0F800000 0x0 0x05400000 /* vi_mem_pool_region[0] 84 MB (default) */
0x0 0x14C00000 0x0 0x01D00000 /* vi_mem_pool_region[1] 29 MB */
0x0 0x16900000 0x0 0x03200000>; /* vi_mem_pool_region[2] 50 MB */
no-map;
};
facelib_mem: memory@22000000 {
reg = <0x0 0x22000000 0x0 0x10000000>;
no-map;
};
};
&adc {
vref-supply = <&reg_vref_1v8>;
status = "okay";
};
&i2c0 {
clock-frequency = <400000>;
status = "disabled";
};
&i2c1 {
clock-frequency = <400000>;
status = "disabled";
};
&audio_i2c0 {
clock-frequency = <100000>;
status = "okay";
es8156_audio_codec: es8156@9 {
#sound-dai-cells = <0>;
compatible = "everest,es8156";
reg = <0x09>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audio_i2s1_mclk>;
};
};
&uart0 {
clock-frequency = <100000000>;
};
&gmac0 {
phy-mode = "rgmii-id";
rx-clk-delay = <0x00>; /* for RGMII */
tx-clk-delay = <0x00>; /* for RGMII */
phy-handle = <&phy_88E1111_0>;
status = "okay";
mdio0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
phy_88E1111_0: ethernet-phy@0 {
reg = <0x1>;
};
};
};
&gmac1 {
status = "disabled";
};
&emmc {
max-frequency = <198000000>;
non-removable;
mmc-hs400-1_8v;
io_fixed_1v8;
is_emmc;
no-sdio;
no-sd;
pull_up;
bus-width = <8>;
status = "okay";
};
&sdhci0 {
max-frequency = <198000000>;
bus-width = <4>;
pull_up;
wprtn_ignore;
status = "okay";
};
&sdhci1 {
status = "okay";
max-frequency = <198000000>;
bus-width = <4>;
pull_up;
no-sd;
no-mmc;
non-removable;
io_fixed_1v8;
post-power-on-delay-ms = <50>;
wprtn_ignore;
cap-sd-highspeed;
keep-power-in-suspend;
mmc-pwrseq = <&wifi_pwrseq>;
#address-cells = <1>;
#size-cells = <0>;
brcmf: wifi@1 {
compatible = "brcm,bcm4329-fmac";
reg = <1>;
};
};
&padctrl0_apsys { /* right-pinctrl */
light-evb-padctrl0 {
/*
* Pin Configuration Node:
* Format: <pin_id mux_node config>
*/
pinctrl_uart0: uart0grp {
thead,pins = <
FM_UART0_TXD 0x0 0x72
FM_UART0_RXD 0x0 0x72
>;
};
pinctrl_spi0: spi0grp {
thead,pins = <
FM_SPI_CSN 0x3 0x20a
FM_SPI_SCLK 0x0 0x20a
FM_SPI_MISO 0x0 0x23a
FM_SPI_MOSI 0x0 0x23a
>;
};
pinctrl_qspi0: qspi0grp {
thead,pins = <
FM_QSPI0_SCLK 0x0 0x20f
FM_QSPI0_CSN0 0x3 0x20f
FM_QSPI0_D0_MOSI 0x0 0x23f
FM_QSPI0_D1_MISO 0x0 0x23f
>;
};
pinctrl_pwm: pwmgrp {
thead,pins = <
FM_QSPI0_D2_WP 0x1 0x208 /* pwm5 */
FM_QSPI0_CSN1 0x1 0x208 /* pwm2 */
>;
};
};
};
&padctrl1_apsys { /* left-pinctrl */
light-evb-padctrl1 {
/*
* Pin Configuration Node:
* Format: <pin_id mux_node config>
*/
pinctrl_uart3: uart3grp {
thead,pins = <
FM_UART3_TXD 0x0 0x72
FM_UART3_RXD 0x0 0x72
>;
};
pinctrl_uart4: uart4grp {
thead,pins = <
FM_UART4_TXD 0x0 0x72
FM_UART4_RXD 0x0 0x72
FM_UART4_CTSN 0x0 0x72
FM_UART4_RTSN 0x0 0x72
>;
};
pinctrl_qspi1: qspi1grp {
thead,pins = <
FM_QSPI1_SCLK 0x0 0x20a
FM_QSPI1_CSN0 0x3 0x20a
FM_QSPI1_D0_MOSI 0x0 0x23a
FM_QSPI1_D1_MISO 0x0 0x23a
FM_QSPI1_D2_WP 0x0 0x23a
FM_QSPI1_D3_HOLD 0x0 0x23a
>;
};
pinctrl_iso7816: iso7816grp {
thead,pins = <
FM_QSPI1_SCLK 0x1 0x208
FM_QSPI1_D0_MOSI 0x1 0x238
FM_QSPI1_D1_MISO 0x1 0x238
FM_QSPI1_D2_WP 0x1 0x238
FM_QSPI1_D3_HOLD 0x1 0x238
>;
};
pinctrl_wireless_power: wireless-power-group {
thead,pins = <
FM_GPIO0_20 0x0 0x23a
>;
};
pinctrl_wireless_host_wake: wireless-host-wake-group {
thead,pins = <
FM_GPIO0_21 0x0 0x21a
>;
};
};
};
&padctrl_aosys {
light-aon-padctrl {
/*
* Pin Configuration Node:
* Format: <pin_id mux_node config>
*/
pinctrl_audiopa1: audiopa1_grp {
thead,pins = <
FM_AUDIO_PA1 0x3 0x72
>;
};
pinctrl_audiopa2: audiopa2_grp {
thead,pins = <
FM_AUDIO_PA2 0x0 0x72
>;
};
pinctrl_volume: volume_grp {
thead,pins = <
FM_CPU_JTG_TDI 0x3 0x208
FM_CPU_JTG_TDO 0x3 0x208
>;
};
};
};
&padctrl_audiosys {
status = "okay";
light-audio-padctrl {
/*
* Pin Configuration Node:
* Format: <pin_id mux_node config>
*/
pinctrl_audio_i2s1_mclk: audio_i2s1_mclk_grp {
thead,pins = <
FM_AUDIO_IO_PA13 0x0 0x20a
>;
};
};
};
&xtensa_dsp {
status = "okay";
};
&xtensa_dsp0 {
status = "okay";
memory-region = <&dsp0_mem>;
};
&xtensa_dsp1{
status = "okay";
memory-region = <&dsp1_mem>;
};
&trng {
status = "disabled";
};
&eip_28 {
status = "okay";
};
&vdec {
status = "okay";
};
&venc {
status = "okay";
};
&isp_venc_shake {
status = "okay";
};
&vidmem {
status = "okay";
memory-region = <&vi_mem>;
};
&gpu {
status = "okay";
};
&npu {
vha_clk_rate = <1000000000>;
status = "okay";
};
&fce {
memory-region = <&facelib_mem>;
status = "okay";
};
&cpus {
c910_0: cpu@0 {
operating-points = <
/* kHz uV */
300000 650000
800000 700000
1500000 800000
1848000 1000000
>;
light,dvddm-operating-points = <
/* kHz uV */
300000 800000
800000 800000
1500000 800000
1848000 1000000
>;
};
c910_1: cpu@1 {
operating-points = <
/* kHz uV */
300000 650000
800000 700000
1500000 800000
1848000 1000000
>;
light,dvddm-operating-points = <
/* kHz uV */
300000 800000
800000 800000
1500000 800000
1848000 1000000
>;
};
c910_2: cpu@2 {
operating-points = <
/* kHz uV */
300000 650000
800000 700000
1500000 800000
1848000 1000000
>;
light,dvddm-operating-points = <
/* kHz uV */
300000 800000
800000 800000
1500000 800000
1848000 1000000
>;
};
c910_3: cpu@3 {
operating-points = <
/* kHz uV */
300000 650000
800000 700000
1500000 800000
1848000 1000000
>;
light,dvddm-operating-points = <
/* kHz uV */
300000 800000
800000 800000
1500000 800000
1848000 1000000
>;
};
};
&dpu {
status = "okay";
};
/* DP1 --- HDMI0 */
&dpu_enc1 {
status = "disabled";
ports {
/delete-node/ port@0;
};
};
&disp1_out {
remote-endpoint = <&hdmi_tx_in>;
};
&hdmi_tx {
status = "okay";
port@0 {
/* input */
hdmi_tx_in: endpoint {
remote-endpoint = <&disp1_out>;
};
};
};
&light_i2s {
status = "okay";
/delete-property/ pinctrl-names;
/delete-property/ pinctrl-0;
};
&i2s0 {
status = "okay";
};
&i2s1 {
status = "okay";
};
&qspi0 {
status = "okay";
num-cs = <1>;
cs-gpios = <&gpio2_porta 3 0>; // GPIO_ACTIVE_HIGH: 0
spi_flash: spi-flash@0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "jedec,spi-nor";
reg = <0x0>;
spi-max-frequency = <50000000>;
spi-tx-bus-width = <1>;
spi-rx-bus-width = <1>;
status = "okay";
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
loader@0 {
label = "loader";
reg = <0x0 0x800000>;
};
};
};
};
&qspi1 {
status = "disabled";
};

View File

@@ -8,6 +8,7 @@
#include <dt-bindings/pinctrl/light-fm-aon-pinctrl.h>
#include <dt-bindings/pinctrl/light-fm-audio-pinctrl.h>
#include <dt-bindings/pinctrl/light-fm-pinctrl-def.h>
#include <dt-bindings/pinctrl/light.h>
#include <dt-bindings/clock/light-fm-ap-clock.h>
#include <dt-bindings/clock/light-vpsys.h>
#include <dt-bindings/clock/light-vosys.h>
@@ -379,7 +380,7 @@
};
};
soc {
soc: soc {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
@@ -1046,7 +1047,7 @@
#size-cells = <0>;
};
g2d: gc620@ffecc80000 {
/* g2d: gc620@ffecc80000 {
compatible = "thead,c910-gc620";
reg = <0xff 0xecc80000 0x0 0x40000>;
interrupt-parent = <&intc>;
@@ -1057,6 +1058,19 @@
<&vpsys_clk_gate LIGHT_VPSYS_G2D_CCLK>;
clock-names = "pclk", "aclk", "cclk";
status = "okay";
};*/
g2d: gpu@13040000 {
compatible = "vivante,gc";
reg = <0xff 0xecc80000 0x0 0x40000>;
clocks = <&vpsys_clk_gate LIGHT_VPSYS_G2D_PCLK>,
<&vpsys_clk_gate LIGHT_VPSYS_G2D_ACLK>,
<&vpsys_clk_gate LIGHT_VPSYS_G2D_CCLK>;
clock-names = "bus", "core", "shader";
interrupt-parent = <&intc>;
interrupts = <101>;
};
dsi0: dw-mipi-dsi0@ffef500000 {

View File

@@ -0,0 +1,71 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2020 - 2022 Deepak Khatri <lorforlinux@beagleboard.org>
* See Cape Interface Spec page for more info on Bone Buses
* https://docs.beagleboard.org/0.0/boards/capes/cape-interface-spec.html#beaglebone-cape-interface-spec
*
*/
/dts-v1/;
/plugin/;
/*
* Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
*/
&{/chosen} {
overlays {
BBORG_LOAD-00A2 = __TIMESTAMP__;
};
};
/*
* Easy load control through sysfs (/sys/class/leds/) using gpio-leds driver
*/
&bone_led_P9_42 {
status = "okay";
label = "load-sink1";
default-state = "keep";
};
&bone_led_P9_41 {
status = "okay";
label = "load-sink2";
default-state = "keep";
};
&bone_led_P9_30 {
status = "okay";
label = "load-sink3";
default-state = "keep";
};
&bone_led_P9_27 {
status = "okay";
label = "load-sink4";
default-state = "keep";
};
&bone_led_P8_12 {
status = "okay";
label = "load-sink5";
default-state = "keep";
};
&bone_led_P8_11 {
status = "okay";
label = "load-sink6";
default-state = "keep";
};
&bone_led_P8_15 {
status = "okay";
label = "load-sink7";
default-state = "keep";
};
&bone_led_P8_17 {
status = "okay";
label = "load-sink8";
default-state = "keep";
};

View File

@@ -0,0 +1,58 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015 Robert Nelson <robertcnelson@gmail.com>
* Copyright (C) 2019 Amilcar Lucas <amilcar.lucas@iav.de>
* Copyright (C) 2020 - 2023 Deepak Khatri <lorforlinux@beagleboard.org>
*
* See Cape Interface Spec page for more info on Bone Buses
* https://docs.beagleboard.org/0.0/boards/capes/cape-interface-spec.html#beaglebone-cape-interface-spec
*
*/
/dts-v1/;
/plugin/;
/*
* Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
*/
&{/chosen} {
overlays {
BBORG_RELAY-00A2.kernel = __TIMESTAMP__;
};
};
/*
* Easy load control through sysfs (/sys/class/leds/) using gpio-leds driver
*/
// relay1
&bone_led_P9_41 {
status = "okay";
// access: sys/class/leds/relay1
label = "relay1";
default-state = "keep";
};
// relay2
&bone_led_P9_42 {
status = "okay";
// access: sys/class/leds/relay2
label = "relay2";
default-state = "keep";
};
// realy3
&bone_led_P9_30 {
status = "okay";
// access: sys/class/leds/relay3
label = "relay3";
default-state = "keep";
};
// realy4
&bone_led_P9_27 {
status = "okay";
// access: sys/class/leds/relay4
label = "relay4";
default-state = "keep";
};

View File

@@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2020 - 2022 Deepak Khatri <lorforlinux@beagleboard.org>
*
* See Cape Interface Spec page for more info on Bone Buses
* https://docs.beagleboard.org/0.0/boards/capes/cape-interface-spec.html#beaglebone-cape-interface-spec
*
* Virtual cape for LED on P8_03
* Supports BBB, BBBWL, BBAI, and BBAI-64
*
*/
/dts-v1/;
/plugin/;
&{/chosen} {
overlays {
BONE-LED_P8_03 = __TIMESTAMP__;
};
};
/*
* Easy LED control through sysfs (/sys/class/leds/) using gpio-leds driver
*/
&bone_led_P8_03 {
status = "okay";
// access: sys/class/leds/led_P8_03
label = "led_P8_03";
linux,default-trigger = "heartbeat";
default-state = "on";
};

View File

@@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2020 - 2022 Deepak Khatri <lorforlinux@beagleboard.org>
*
* See Cape Interface Spec page for more info on Bone Buses
* https://docs.beagleboard.org/0.0/boards/capes/cape-interface-spec.html#beaglebone-cape-interface-spec
*
* Virtual cape for LED on P9_11
* Supports BBB, BBBWL, BBAI, and BBAI-64
*
*/
/dts-v1/;
/plugin/;
&{/chosen} {
overlays {
BONE-LED_P9_11 = __TIMESTAMP__;
};
};
/*
* Easy LED control through sysfs (/sys/class/leds/) using gpio-leds driver
*/
&bone_led_P9_11 {
status = "okay";
// access: sys/class/leds/led_P9_11
label = "led_P9_11";
linux,default-trigger = "heartbeat";
default-state = "on";
};

View File

@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2023 BeagleBoard.org - https://beagleboard.org/
* Copyright (C) 2023 Deepak Khatri <lorforlinux@beagleboard.org>
*
* See Cape Interface Spec page for more info on Bone Buses
* https://docs.beagleboard.org/0.0/boards/capes/cape-interface-spec.html
*
*/
/dts-v1/;
/plugin/;
/*
* Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
*/
&{/chosen} {
overlays {
BBORG_LOAD-00A2 = __TIMESTAMP__;
};
};
/*
* Enable mikroBus port
*/
&bone_mikrobus0 {
status = "okay";
};

View File

@@ -0,0 +1,14 @@
# Overlays for the CONFIG_SOC_THEAD platform
dtbo-$(CONFIG_SOC_THEAD) += \
BBORG_LOAD-00A2.dtbo \
BBORG_RELAY-00A2.dtbo \
BONE-LED_P8_03.dtbo \
BONE-LED_P9_11.dtbo \
BVA-MIKROBUS-0.dtbo
targets += dtbs dtbs_install
targets += $(dtbo-y)
always-y := $(dtbo-y)
clean-files := *.dtbo

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -73,32 +73,44 @@ CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
CONFIG_NET_IPVTI=y
CONFIG_INET_ESP=y
CONFIG_TCP_CONG_ADVANCED=y
CONFIG_TCP_CONG_BBR=m
CONFIG_NETFILTER=y
CONFIG_BRIDGE_NETFILTER=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_FTP=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_NAT=y
CONFIG_NETFILTER_XT_CONNMARK=y
CONFIG_NETFILTER_XT_NAT=y
CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
CONFIG_NETFILTER_XT_TARGET_REDIRECT=y
CONFIG_NETFILTER_XT_TARGET_MASQUERADE=y
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_IPVS=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_TCP_CONG_ADVANCED=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_TCP_CONG_WESTWOOD=m
CONFIG_TCP_CONG_BBR=m
CONFIG_IP_VS=y
CONFIG_IP_VS_PROTO_TCP=y
CONFIG_IP_VS_PROTO_UDP=y
CONFIG_IP_VS_RR=y
CONFIG_IP_VS_NFCT=y
CONFIG_NF_LOG_ARP=m
CONFIG_NF_LOG_IPV4=m
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_NAT=y
CONFIG_IP_NF_TARGET_MASQUERADE=y
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_NAT=y
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_MANGLE=m
CONFIG_NF_LOG_IPV6=m
CONFIG_IP6_NF_IPTABLES=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_NAT=m
CONFIG_BRIDGE=y
CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_VLAN_8021Q=y
@@ -160,12 +172,17 @@ CONFIG_USB_USBNET=m
# CONFIG_USB_NET_AX88179_178A is not set
# CONFIG_USB_NET_NET1080 is not set
CONFIG_RTL8723DS=y
CONFIG_AIC_WLAN_SUPPORT=y
CONFIG_AIC_FW_PATH="/lib/firmware/aic8800"
CONFIG_AIC8800_WLAN_SUPPORT=m
CONFIG_AIC8800_BTLPM_SUPPORT=m
CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_GPIO=y
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_GOODIX=y
CONFIG_TOUCHSCREEN_GT9XX=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_SERIAL_8250=y
@@ -258,6 +275,7 @@ CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_ILITEK_ILI9881C=y
CONFIG_DRM_PANEL_ILI9881D=y
CONFIG_DRM_PANEL_HX8394=y
CONFIG_DRM_PANEL_JADARD_JD9365DA_H3=y
CONFIG_DRM_VERISILICON=y
CONFIG_DRM_POWERVR_ROGUE=m
CONFIG_BACKLIGHT_CLASS_DEVICE=y
@@ -383,8 +401,8 @@ CONFIG_HWSPINLOCK_LIGHT_TEST=m
CONFIG_MAILBOX=y
CONFIG_RPMSG=y
CONFIG_RPMSG_CHAR=y
CONFIG_RPMSG_VIRTIO=y
CONFIG_RPMSG_THEAD_LIGHT=y
CONFIG_RPMSG_VIRTIO=y
CONFIG_EXTCON=y
CONFIG_IIO=y
CONFIG_IIO_SW_DEVICE=y
@@ -394,7 +412,8 @@ CONFIG_NVMEM_THEAD_LIGHT_EFUSE=y
CONFIG_TEE=y
CONFIG_OPTEE=y
CONFIG_OPTEE_BENCHMARK=y
CONFIG_LIGHT_GPU_VIV=m
# CONFIG_LIGHT_GPU_VIV is not set
CONFIG_DRM_ETNAVIV=m
# CONFIG_LIGHT_NET is not set
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y

View File

@@ -396,4 +396,22 @@ static inline ulong __xchg16_relaxed(ulong new, void *ptr)
cmpxchg_relaxed((ptr), (o), (n)); \
})
#define cmpxchg64_relaxed(ptr, o, n) \
({ \
BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
cmpxchg_relaxed((ptr), (o), (n)); \
})
#define cmpxchg64_acquire(ptr, o, n) \
({ \
BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
cmpxchg_acquire((ptr), (o), (n)); \
})
#define cmpxchg64_release(ptr, o, n) \
({ \
BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
cmpxchg_release((ptr), (o), (n)); \
})
#endif /* _ASM_RISCV_CMPXCHG_H */

View File

@@ -115,14 +115,6 @@ config BT_HCIUART_H4
Say Y here to compile support for HCI UART (H4) protocol.
config BT_HCIUART_RTL3WIRE
bool "Realtek Three-wire UART (H5) protocol support"
depends on BT_HCIUART
help
Realtek Three-wire UART (H5) transport layer makes it possible
to use Realtek Bluetooth controller with Three-wire UART.
Say Y here to compile support for Realtek Three-wire UART.
config BT_HCIUART_NOKIA
tristate "UART Nokia H4+ protocol support"
depends on BT_HCIUART

View File

@@ -45,6 +45,4 @@ hci_uart-$(CONFIG_BT_HCIUART_BCM) += hci_bcm.o
hci_uart-$(CONFIG_BT_HCIUART_QCA) += hci_qca.o
hci_uart-$(CONFIG_BT_HCIUART_AG6XX) += hci_ag6xx.o
hci_uart-$(CONFIG_BT_HCIUART_MRVL) += hci_mrvl.o
hci_uart-y += rtk_coex.o
hci_uart-$(CONFIG_BT_HCIUART_RTL3WIRE) += hci_rtk_h5.o
hci_uart-objs := $(hci_uart-y)

View File

@@ -654,7 +654,6 @@ static const struct h4_recv_pkt bcm_recv_pkts[] = {
{ H4_RECV_ACL, .recv = hci_recv_frame },
{ H4_RECV_SCO, .recv = hci_recv_frame },
{ H4_RECV_EVENT, .recv = hci_recv_frame },
{ H4_RECV_ISO, .recv = hci_recv_frame },
{ BCM_RECV_LM_DIAG, .recv = hci_recv_diag },
{ BCM_RECV_NULL, .recv = hci_recv_diag },
{ BCM_RECV_TYPE49, .recv = hci_recv_diag },

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
*
* Bluetooth HCI UART driver
@@ -5,25 +6,10 @@
* Copyright (C) 2000-2001 Qualcomm Incorporated
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
@@ -31,6 +17,7 @@
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/errno.h>
@@ -38,32 +25,18 @@
#include <linux/signal.h>
#include <linux/ioctl.h>
#include <linux/skbuff.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <linux/version.h>
#include "hci_uart.h"
#ifdef BTCOEX
#include "rtk_coex.h"
#endif
//#define VERSION "1.2"
struct h4_struct {
unsigned long rx_state;
unsigned long rx_count;
struct sk_buff *rx_skb;
struct sk_buff_head txq;
};
/* H4 receiver States */
#define H4_W4_PACKET_TYPE 0
#define H4_W4_EVENT_HDR 1
#define H4_W4_ACL_HDR 2
#define H4_W4_SCO_HDR 3
#define H4_W4_DATA 4
/* Initialize protocol */
static int h4_open(struct hci_uart *hu)
{
@@ -71,7 +44,7 @@ static int h4_open(struct hci_uart *hu)
BT_DBG("hu %p", hu);
h4 = kzalloc(sizeof(*h4), GFP_ATOMIC);
h4 = kzalloc(sizeof(*h4), GFP_KERNEL);
if (!h4)
return -ENOMEM;
@@ -98,8 +71,6 @@ static int h4_close(struct hci_uart *hu)
{
struct h4_struct *h4 = hu->priv;
hu->priv = NULL;
BT_DBG("hu %p", hu);
skb_queue_purge(&h4->txq);
@@ -112,7 +83,7 @@ static int h4_close(struct hci_uart *hu)
return 0;
}
/* Enqueue frame for transmittion (padding, crc, etc) */
/* Enqueue frame for transmission (padding, crc, etc) */
static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{
struct h4_struct *h4 = hu->priv;
@@ -120,174 +91,34 @@ static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
BT_DBG("hu %p skb %p", hu, skb);
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
skb_queue_tail(&h4->txq, skb);
return 0;
}
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
static inline int h4_check_data_len(struct h4_struct *h4, int len)
#else
static inline int h4_check_data_len(struct hci_dev *hdev, struct h4_struct *h4, int len)
#endif
{
register int room = skb_tailroom(h4->rx_skb);
BT_DBG("len %d room %d", len, room);
if (!len) {
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
hci_recv_frame(h4->rx_skb);
#else
hci_recv_frame(hdev, h4->rx_skb);
#endif
} else if (len > room) {
BT_ERR("Data length is too large");
kfree_skb(h4->rx_skb);
} else {
h4->rx_state = H4_W4_DATA;
h4->rx_count = len;
return len;
}
h4->rx_state = H4_W4_PACKET_TYPE;
h4->rx_skb = NULL;
h4->rx_count = 0;
return 0;
}
static const struct h4_recv_pkt h4_recv_pkts[] = {
{ H4_RECV_ACL, .recv = hci_recv_frame },
{ H4_RECV_SCO, .recv = hci_recv_frame },
{ H4_RECV_EVENT, .recv = hci_recv_frame },
{ H4_RECV_ISO, .recv = hci_recv_frame },
};
/* Recv data */
static int h4_recv(struct hci_uart *hu, void *data, int count)
static int h4_recv(struct hci_uart *hu, const void *data, int count)
{
struct h4_struct *h4 = hu->priv;
register char *ptr;
struct hci_event_hdr *eh;
struct hci_acl_hdr *ah;
struct hci_sco_hdr *sh;
register int len, type, dlen;
BT_DBG("hu %p count %d rx_state %ld rx_count %ld",
hu, count, h4->rx_state, h4->rx_count);
if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
return -EUNATCH;
ptr = data;
while (count) {
if (h4->rx_count) {
len = min_t(unsigned int, h4->rx_count, count);
memcpy(skb_put(h4->rx_skb, len), ptr, len);
h4->rx_count -= len; count -= len; ptr += len;
if (h4->rx_count)
continue;
switch (h4->rx_state) {
case H4_W4_DATA:
BT_DBG("Complete data");
#ifdef BTCOEX
if(bt_cb(h4->rx_skb)->pkt_type == HCI_EVENT_PKT)
rtk_btcoex_parse_event(
h4->rx_skb->data,
h4->rx_skb->len);
if(bt_cb(h4->rx_skb)->pkt_type == HCI_ACLDATA_PKT)
rtk_btcoex_parse_l2cap_data_rx(
h4->rx_skb->data,
h4->rx_skb->len);
#endif
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
hci_recv_frame(h4->rx_skb);
#else
hci_recv_frame(hu->hdev, h4->rx_skb);
#endif
h4->rx_state = H4_W4_PACKET_TYPE;
h4->rx_skb = NULL;
continue;
case H4_W4_EVENT_HDR:
eh = hci_event_hdr(h4->rx_skb);
BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
h4_check_data_len(h4, eh->plen);
#else
h4_check_data_len(hu->hdev, h4, eh->plen);
#endif
continue;
case H4_W4_ACL_HDR:
ah = hci_acl_hdr(h4->rx_skb);
dlen = __le16_to_cpu(ah->dlen);
BT_DBG("ACL header: dlen %d", dlen);
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
h4_check_data_len(h4, dlen);
#else
h4_check_data_len(hu->hdev, h4, dlen);
#endif
continue;
case H4_W4_SCO_HDR:
sh = hci_sco_hdr(h4->rx_skb);
BT_DBG("SCO header: dlen %d", sh->dlen);
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
h4_check_data_len(h4, sh->dlen);
#else
h4_check_data_len(hu->hdev, h4, sh->dlen);
#endif
continue;
}
}
/* H4_W4_PACKET_TYPE */
switch (*ptr) {
case HCI_EVENT_PKT:
BT_DBG("Event packet");
h4->rx_state = H4_W4_EVENT_HDR;
h4->rx_count = HCI_EVENT_HDR_SIZE;
type = HCI_EVENT_PKT;
break;
case HCI_ACLDATA_PKT:
BT_DBG("ACL packet");
h4->rx_state = H4_W4_ACL_HDR;
h4->rx_count = HCI_ACL_HDR_SIZE;
type = HCI_ACLDATA_PKT;
break;
case HCI_SCODATA_PKT:
BT_DBG("SCO packet");
h4->rx_state = H4_W4_SCO_HDR;
h4->rx_count = HCI_SCO_HDR_SIZE;
type = HCI_SCODATA_PKT;
break;
default:
BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
hu->hdev->stat.err_rx++;
ptr++; count--;
continue;
};
ptr++; count--;
/* Allocate packet */
h4->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
if (!h4->rx_skb) {
BT_ERR("Can't allocate mem for new packet");
h4->rx_state = H4_W4_PACKET_TYPE;
h4->rx_count = 0;
return -ENOMEM;
}
h4->rx_skb->dev = (void *) hu->hdev;
bt_cb(h4->rx_skb)->pkt_type = type;
h4->rx_skb = h4_recv_buf(hu->hdev, h4->rx_skb, data, count,
h4_recv_pkts, ARRAY_SIZE(h4_recv_pkts));
if (IS_ERR(h4->rx_skb)) {
int err = PTR_ERR(h4->rx_skb);
bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err);
h4->rx_skb = NULL;
return err;
}
return count;
@@ -299,8 +130,9 @@ static struct sk_buff *h4_dequeue(struct hci_uart *hu)
return skb_dequeue(&h4->txq);
}
static struct hci_uart_proto h4p = {
static const struct hci_uart_proto h4p = {
.id = HCI_UART_H4,
.name = "H4",
.open = h4_open,
.close = h4_close,
.recv = h4_recv,
@@ -311,17 +143,132 @@ static struct hci_uart_proto h4p = {
int __init h4_init(void)
{
int err = hci_uart_register_proto(&h4p);
if (!err)
BT_INFO("HCI H4 protocol initialized");
else
BT_ERR("HCI H4 protocol registration failed");
return err;
return hci_uart_register_proto(&h4p);
}
int __exit h4_deinit(void)
{
return hci_uart_unregister_proto(&h4p);
}
struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
const unsigned char *buffer, int count,
const struct h4_recv_pkt *pkts, int pkts_count)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
u8 alignment = hu->alignment ? hu->alignment : 1;
/* Check for error from previous call */
if (IS_ERR(skb))
skb = NULL;
while (count) {
int i, len;
/* remove padding bytes from buffer */
for (; hu->padding && count > 0; hu->padding--) {
count--;
buffer++;
}
if (!count)
break;
if (!skb) {
for (i = 0; i < pkts_count; i++) {
if (buffer[0] != (&pkts[i])->type)
continue;
skb = bt_skb_alloc((&pkts[i])->maxlen,
GFP_ATOMIC);
if (!skb)
return ERR_PTR(-ENOMEM);
hci_skb_pkt_type(skb) = (&pkts[i])->type;
hci_skb_expect(skb) = (&pkts[i])->hlen;
break;
}
/* Check for invalid packet type */
if (!skb)
return ERR_PTR(-EILSEQ);
count -= 1;
buffer += 1;
}
len = min_t(uint, hci_skb_expect(skb) - skb->len, count);
skb_put_data(skb, buffer, len);
count -= len;
buffer += len;
/* Check for partial packet */
if (skb->len < hci_skb_expect(skb))
continue;
for (i = 0; i < pkts_count; i++) {
if (hci_skb_pkt_type(skb) == (&pkts[i])->type)
break;
}
if (i >= pkts_count) {
kfree_skb(skb);
return ERR_PTR(-EILSEQ);
}
if (skb->len == (&pkts[i])->hlen) {
u16 dlen;
switch ((&pkts[i])->lsize) {
case 0:
/* No variable data length */
dlen = 0;
break;
case 1:
/* Single octet variable length */
dlen = skb->data[(&pkts[i])->loff];
hci_skb_expect(skb) += dlen;
if (skb_tailroom(skb) < dlen) {
kfree_skb(skb);
return ERR_PTR(-EMSGSIZE);
}
break;
case 2:
/* Double octet variable length */
dlen = get_unaligned_le16(skb->data +
(&pkts[i])->loff);
hci_skb_expect(skb) += dlen;
if (skb_tailroom(skb) < dlen) {
kfree_skb(skb);
return ERR_PTR(-EMSGSIZE);
}
break;
default:
/* Unsupported variable length */
kfree_skb(skb);
return ERR_PTR(-EILSEQ);
}
if (!dlen) {
hu->padding = (skb->len - 1) % alignment;
hu->padding = (alignment - hu->padding) % alignment;
/* No more data, complete frame */
(&pkts[i])->recv(hdev, skb);
skb = NULL;
}
} else {
hu->padding = (skb->len - 1) % alignment;
hu->padding = (alignment - hu->padding) % alignment;
/* Complete frame */
(&pkts[i])->recv(hdev, skb);
skb = NULL;
}
}
return skb;
}
EXPORT_SYMBOL_GPL(h4_recv_buf);

File diff suppressed because it is too large Load Diff

View File

@@ -1,908 +0,0 @@
/*
*
* Bluetooth HCI UART driver
*
* Copyright (C) 2011-2014 wifi_fae<wifi_fae@realtek.com.tw>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/signal.h>
#include <linux/ioctl.h>
#include <linux/skbuff.h>
#include <linux/bitrev.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <linux/version.h>
#include "hci_uart.h"
#ifdef BTCOEX
#include "rtk_coex.h"
#endif
//#define VERSION "1.0"
static int txcrc = 1;
//static int hciextn = 1;
#define H5_TXWINSIZE 4
#define H5_ACK_PKT 0x00
#define H5_LE_PKT 0x0F
#define H5_VDRSPEC_PKT 0x0E
struct h5_struct {
struct sk_buff_head unack; /* Unack'ed packets queue */
struct sk_buff_head rel; /* Reliable packets queue */
struct sk_buff_head unrel; /* Unreliable packets queue */
unsigned long rx_count;
struct sk_buff *rx_skb;
struct delayed_work retrans_work;
struct hci_uart *hu; /* Parent HCI UART */
enum {
H5_W4_PKT_DELIMITER,
H5_W4_PKT_START,
H5_W4_HDR,
H5_W4_DATA,
H5_W4_CRC
} rx_state;
enum {
H5_ESCSTATE_NOESC,
H5_ESCSTATE_ESC
} rx_esc_state;
u16 message_crc;
u8 use_crc;
u8 rxack; /* Last packet sent by us that the peer ack'ed */
u8 rxseq_txack; /* rxseq == txack. */
u8 txack_req; /* Do we need to send ack's to the peer? */
/* Reliable packet sequence number - used to assign seq to each rel pkt. */
u8 msgq_txseq;
/* The spin lock protects seq, ack and ack req */
spinlock_t lock;
};
/* ---- H5 CRC calculation ---- */
/* Table for calculating CRC for polynomial 0x1021, LSB processed first,
initial value 0xffff, bits shifted in reverse order. */
static const u16 crc_table[] = {
0x0000, 0x1081, 0x2102, 0x3183,
0x4204, 0x5285, 0x6306, 0x7387,
0x8408, 0x9489, 0xa50a, 0xb58b,
0xc60c, 0xd68d, 0xe70e, 0xf78f
};
/* Initialise the crc calculator */
#define H5_CRC_INIT(x) x = 0xffff
/*
Update crc with next data byte
Implementation note
The data byte is treated as two nibbles. The crc is generated
in reverse, i.e., bits are fed into the register from the top.
*/
static void h5_crc_update(u16 * crc, u8 d)
{
u16 reg = *crc;
reg = (reg >> 4) ^ crc_table[(reg ^ d) & 0x000f];
reg = (reg >> 4) ^ crc_table[(reg ^ (d >> 4)) & 0x000f];
*crc = reg;
}
/* ---- H5 core ---- */
static void h5_slip_msgdelim(struct sk_buff *skb)
{
const char pkt_delim = 0xc0;
memcpy(skb_put(skb, 1), &pkt_delim, 1);
}
static void h5_slip_one_byte(struct sk_buff *skb, u8 c)
{
const char esc_c0[2] = { 0xdb, 0xdc };
const char esc_db[2] = { 0xdb, 0xdd };
const char esc_11[2] = { 0xdb, 0xde };
const char esc_13[2] = { 0xdb, 0xdf };
switch (c) {
case 0xc0:
memcpy(skb_put(skb, 2), &esc_c0, 2);
break;
case 0xdb:
memcpy(skb_put(skb, 2), &esc_db, 2);
break;
case 0x11:
memcpy(skb_put(skb, 2), &esc_11, 2);
break;
case 0x13:
memcpy(skb_put(skb, 2), &esc_13, 2);
break;
default:
memcpy(skb_put(skb, 1), &c, 1);
}
}
static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{
struct h5_struct *h5 = hu->priv;
if (skb->len > 0xFFF) { //Pkt length must be less than 4095 bytes
BT_ERR("Packet too long");
kfree_skb(skb);
return 0;
}
switch (bt_cb(skb)->pkt_type) {
case HCI_ACLDATA_PKT:
case HCI_COMMAND_PKT:
skb_queue_tail(&h5->rel, skb);
break;
case HCI_SCODATA_PKT:
skb_queue_tail(&h5->unrel, skb);
break;
case H5_LE_PKT:
case H5_ACK_PKT:
case H5_VDRSPEC_PKT:
skb_queue_tail(&h5->unrel, skb); /* 3-wire LinkEstablishment */
break;
default:
BT_ERR("Unknown packet type");
kfree_skb(skb);
break;
}
return 0;
}
static struct sk_buff *h5_prepare_pkt(struct h5_struct *h5, u8 * data,
int len, int pkt_type)
{
struct sk_buff *nskb;
u8 hdr[4], chan;
u16 H5_CRC_INIT(h5_txmsg_crc);
int rel, i;
u8 tmp;
unsigned long flags;
switch (pkt_type) {
case HCI_ACLDATA_PKT:
chan = 2; /* 3-wire ACL channel */
rel = 1; /* reliable channel */
break;
case HCI_COMMAND_PKT:
chan = 1; /* 3-wire cmd channel */
rel = 1; /* reliable channel */
break;
case HCI_EVENT_PKT:
chan = 4; /* 3-wire cmd channel */
rel = 1; /* reliable channel */
break;
case HCI_SCODATA_PKT:
chan = 3; /* 3-wire SCO channel */
rel = 0; /* unreliable channel */
break;
case H5_LE_PKT:
chan = 15; /* 3-wire LinkEstablishment channel */
rel = 0; /* unreliable channel */
break;
case H5_ACK_PKT:
chan = 0; /* 3-wire ACK channel */
rel = 0; /* unreliable channel */
break;
case H5_VDRSPEC_PKT:
chan = 14; /* 3-wire Vendor Specific channel */
rel = 0; /* unreliable channel */
break;
default:
BT_ERR("Unknown packet type");
return NULL;
}
/* Max len of packet: (original len +4(h5 hdr) +2(crc))*2
(because bytes 0xc0 and 0xdb are escaped, worst case is
when the packet is all made of 0xc0 and 0xdb :) )
+ 2 (0xc0 delimiters at start and end). */
nskb = alloc_skb((len + 6) * 2 + 2, GFP_ATOMIC);
if (!nskb)
return NULL;
bt_cb(nskb)->pkt_type = pkt_type;
h5_slip_msgdelim(nskb);
spin_lock_irqsave(&h5->lock, flags);
tmp = h5->rxseq_txack;
hdr[0] = h5->rxseq_txack << 3;
h5->txack_req = 0;
spin_unlock_irqrestore(&h5->lock, flags);
BT_DBG("We request packet no %u to card", tmp);
if (rel) {
spin_lock_irqsave(&h5->lock, flags);
tmp = h5->msgq_txseq;
hdr[0] |= 0x80 + h5->msgq_txseq;
h5->msgq_txseq = (h5->msgq_txseq + 1) & 0x07;
spin_unlock_irqrestore(&h5->lock, flags);
BT_DBG("Sending packet with seqno %u", tmp);
}
if (h5->use_crc)
hdr[0] |= 0x40;
hdr[1] = ((len << 4) & 0xff) | chan;
hdr[2] = len >> 4;
hdr[3] = ~(hdr[0] + hdr[1] + hdr[2]);
/* Put H5 header */
for (i = 0; i < 4; i++) {
h5_slip_one_byte(nskb, hdr[i]);
if (h5->use_crc)
h5_crc_update(&h5_txmsg_crc, hdr[i]);
}
/* Put payload */
for (i = 0; i < len; i++) {
h5_slip_one_byte(nskb, data[i]);
if (h5->use_crc)
h5_crc_update(&h5_txmsg_crc, data[i]);
}
/* Put CRC */
if (h5->use_crc) {
h5_txmsg_crc = bitrev16(h5_txmsg_crc);
h5_slip_one_byte(nskb, (u8) ((h5_txmsg_crc >> 8) & 0x00ff));
h5_slip_one_byte(nskb, (u8) (h5_txmsg_crc & 0x00ff));
}
h5_slip_msgdelim(nskb);
return nskb;
}
/* This is a rewrite of pkt_avail in AH5 */
static struct sk_buff *h5_dequeue(struct hci_uart *hu)
{
struct h5_struct *h5 = hu->priv;
unsigned long flags;
struct sk_buff *skb;
/* First of all, check for unreliable messages in the queue,
since they have priority */
if ((skb = skb_dequeue(&h5->unrel)) != NULL) {
struct sk_buff *nskb =
h5_prepare_pkt(h5, skb->data, skb->len,
bt_cb(skb)->pkt_type);
if (nskb) {
kfree_skb(skb);
return nskb;
} else {
skb_queue_head(&h5->unrel, skb);
BT_ERR
("Could not dequeue pkt because alloc_skb failed");
}
}
/* Now, try to send a reliable pkt. We can only send a
reliable packet if the number of packets sent but not yet ack'ed
is < than the winsize */
spin_lock_irqsave_nested(&h5->unack.lock, flags, SINGLE_DEPTH_NESTING);
if (h5->unack.qlen < H5_TXWINSIZE
&& (skb = skb_dequeue(&h5->rel)) != NULL) {
struct sk_buff *nskb =
h5_prepare_pkt(h5, skb->data, skb->len,
bt_cb(skb)->pkt_type);
if (nskb) {
__skb_queue_tail(&h5->unack, skb);
schedule_delayed_work(&h5->retrans_work, HZ / 4);
spin_unlock_irqrestore(&h5->unack.lock, flags);
return nskb;
} else {
skb_queue_head(&h5->rel, skb);
BT_ERR
("Could not dequeue pkt because alloc_skb failed");
}
}
spin_unlock_irqrestore(&h5->unack.lock, flags);
/* We could not send a reliable packet, either because there are
none or because there are too many unack'ed pkts. Did we receive
any packets we have not acknowledged yet ? */
if (h5->txack_req) {
/* if so, craft an empty ACK pkt and send it on H5 unreliable
channel 0 */
struct sk_buff *nskb = h5_prepare_pkt(h5, NULL, 0, H5_ACK_PKT);
return nskb;
}
/* We have nothing to send */
return NULL;
}
static int h5_flush(struct hci_uart *hu)
{
BT_DBG("hu %p", hu);
return 0;
}
/* Remove ack'ed packets */
static void h5_pkt_cull(struct h5_struct *h5)
{
struct sk_buff *skb, *tmp;
unsigned long flags;
int i, pkts_to_be_removed;
u8 seqno;
spin_lock_irqsave(&h5->unack.lock, flags);
pkts_to_be_removed = skb_queue_len(&h5->unack);
seqno = h5->msgq_txseq;
while (pkts_to_be_removed) {
if (h5->rxack == seqno)
break;
pkts_to_be_removed--;
seqno = (seqno - 1) & 0x07;
}
if (h5->rxack != seqno)
BT_ERR("Peer acked invalid packet");
BT_DBG("Removing %u pkts out of %u, up to seqno %u",
pkts_to_be_removed, skb_queue_len(&h5->unack),
(seqno - 1) & 0x07);
i = 0;
skb_queue_walk_safe(&h5->unack, skb, tmp) {
if (i >= pkts_to_be_removed)
break;
i++;
__skb_unlink(skb, &h5->unack);
kfree_skb(skb);
}
if (skb_queue_empty(&h5->unack))
cancel_delayed_work(&h5->retrans_work);
spin_unlock_irqrestore(&h5->unack.lock, flags);
if (i != pkts_to_be_removed)
BT_ERR("Removed only %u out of %u pkts", i, pkts_to_be_removed);
}
/* Handle H5 link-establishment packets. When we
detect a "sync" packet, symptom that the BT module has reset,
we do nothing :) (yet) */
#if 0
static void h5_handle_le_pkt(struct hci_uart *hu)
{
struct h5_struct *h5 = hu->priv;
u8 conf_pkt[2] = { 0x03, 0xfc };
u8 conf_rsp_pkt[3] = { 0x04, 0x7b, 0x00 };
u8 sync_pkt[2] = { 0x01, 0x7e };
u8 sync_rsp_pkt[2] = { 0x02, 0x7d };
u8 wakeup_pkt[2] = { 0x05, 0xfa };
u8 woken_pkt[2] = { 0x06, 0xf9 };
u8 sleep_pkt[2] = { 0x07, 0x78 };
/* spot "conf" pkts and reply with a "conf rsp" pkt */
if (h5->rx_skb->data[1] >> 4 == 2 && h5->rx_skb->data[2] == 0 &&
!memcmp(&h5->rx_skb->data[4], conf_pkt, 2)) {
struct sk_buff *nskb = alloc_skb(3, GFP_ATOMIC);
BT_DBG("Found a LE conf pkt");
if (!nskb)
return;
conf_rsp_pkt[2] |= txcrc << 0x4; //crc check enable, version no = 0. needed to be as avariable.
memcpy(skb_put(nskb, 3), conf_rsp_pkt, 3);
bt_cb(nskb)->pkt_type = H5_LE_PKT;
skb_queue_head(&h5->unrel, nskb);
hci_uart_tx_wakeup(hu);
}
/* spot "conf resp" pkts */
else if (h5->rx_skb->data[1] >> 4 == 2 && h5->rx_skb->data[2] == 0 &&
!memcmp(&h5->rx_skb->data[4], conf_rsp_pkt, 2)) {
BT_DBG("Found a LE conf resp pkt, device go into active state");
txcrc = (h5->rx_skb->data[6] >> 0x4) & 0x1;
}
/* Spot "sync" pkts. If we find one...disaster! */
else if (h5->rx_skb->data[1] >> 4 == 2 && h5->rx_skb->data[2] == 0 &&
!memcmp(&h5->rx_skb->data[4], sync_pkt, 2)) {
BT_ERR("Found a LE sync pkt, card has reset");
//DO Something here
}
/* Spot "sync resp" pkts. If we find one...disaster! */
else if (h5->rx_skb->data[1] >> 4 == 2 && h5->rx_skb->data[2] == 0 &&
!memcmp(&h5->rx_skb->data[4], sync_rsp_pkt, 2)) {
BT_ERR
("Found a LE sync resp pkt, device go into initialized state");
// DO Something here
}
/* Spot "wakeup" pkts. reply woken message when in active mode */
else if (h5->rx_skb->data[1] >> 4 == 2 && h5->rx_skb->data[2] == 0 &&
!memcmp(&h5->rx_skb->data[4], wakeup_pkt, 2)) {
struct sk_buff *nskb = alloc_skb(2, GFP_ATOMIC);
BT_ERR("Found a LE Wakeup pkt, and reply woken message");
// DO Something here
memcpy(skb_put(nskb, 2), woken_pkt, 2);
bt_cb(nskb)->pkt_type = H5_LE_PKT;
skb_queue_head(&h5->unrel, nskb);
hci_uart_tx_wakeup(hu);
}
/* Spot "woken" pkts. receive woken message from device */
else if (h5->rx_skb->data[1] >> 4 == 2 && h5->rx_skb->data[2] == 0 &&
!memcmp(&h5->rx_skb->data[4], woken_pkt, 2)) {
BT_ERR("Found a LE woken pkt from device");
// DO Something here
}
/* Spot "Sleep" pkts */
else if (h5->rx_skb->data[1] >> 4 == 2 && h5->rx_skb->data[2] == 0 &&
!memcmp(&h5->rx_indent: Standard input:620: Error:Unmatched 'else'
skb->data[4], sleep_pkt, 2)) {
BT_ERR("Found a LE Sleep pkt");
// DO Something here
}
}
#endif
static inline void h5_unslip_one_byte(struct h5_struct *h5, unsigned char byte)
{
const u8 c0 = 0xc0, db = 0xdb;
const u8 oof1 = 0x11, oof2 = 0x13;
switch (h5->rx_esc_state) {
case H5_ESCSTATE_NOESC:
switch (byte) {
case 0xdb:
h5->rx_esc_state = H5_ESCSTATE_ESC;
break;
default:
memcpy(skb_put(h5->rx_skb, 1), &byte, 1);
if ((h5->rx_skb->data[0] & 0x40) != 0 &&
h5->rx_state != H5_W4_CRC)
h5_crc_update(&h5->message_crc, byte);
h5->rx_count--;
}
break;
case H5_ESCSTATE_ESC:
switch (byte) {
case 0xdc:
memcpy(skb_put(h5->rx_skb, 1), &c0, 1);
if ((h5->rx_skb->data[0] & 0x40) != 0 &&
h5->rx_state != H5_W4_CRC)
h5_crc_update(&h5->message_crc, 0xc0);
h5->rx_esc_state = H5_ESCSTATE_NOESC;
h5->rx_count--;
break;
case 0xdd:
memcpy(skb_put(h5->rx_skb, 1), &db, 1);
if ((h5->rx_skb->data[0] & 0x40) != 0 &&
h5->rx_state != H5_W4_CRC)
h5_crc_update(&h5->message_crc, 0xdb);
h5->rx_esc_state = H5_ESCSTATE_NOESC;
h5->rx_count--;
break;
case 0xde:
memcpy(skb_put(h5->rx_skb, 1), &oof1, 1);
if ((h5->rx_skb->data[0] & 0x40) != 0
&& h5->rx_state != H5_W4_CRC)
h5_crc_update(&h5->message_crc, oof1);
h5->rx_esc_state = H5_ESCSTATE_NOESC;
h5->rx_count--;
break;
case 0xdf:
memcpy(skb_put(h5->rx_skb, 1), &oof2, 1);
if ((h5->rx_skb->data[0] & 0x40) != 0
&& h5->rx_state != H5_W4_CRC)
h5_crc_update(&h5->message_crc, oof2);
h5->rx_esc_state = H5_ESCSTATE_NOESC;
h5->rx_count--;
break;
default:
BT_ERR("Invalid byte %02x after esc byte", byte);
kfree_skb(h5->rx_skb);
h5->rx_skb = NULL;
h5->rx_state = H5_W4_PKT_DELIMITER;
h5->rx_count = 0;
}
}
}
static void h5_complete_rx_pkt(struct hci_uart *hu)
{
struct h5_struct *h5 = hu->priv;
int pass_up;
if (h5->rx_skb->data[0] & 0x80) { /* reliable pkt */
unsigned long flags;
u8 rxseq;
spin_lock_irqsave(&h5->lock, flags);
rxseq = h5->rxseq_txack;
h5->rxseq_txack++;
h5->rxseq_txack %= 0x8;
h5->txack_req = 1;
spin_unlock_irqrestore(&h5->lock, flags);
BT_DBG("Received seqno %u from card", rxseq);
}
h5->rxack = (h5->rx_skb->data[0] >> 3) & 0x07;
BT_DBG("Request for pkt %u from card", h5->rxack);
h5_pkt_cull(h5);
hci_uart_tx_wakeup(hu);
if ((h5->rx_skb->data[1] & 0x0f) == 2 && h5->rx_skb->data[0] & 0x80) {
bt_cb(h5->rx_skb)->pkt_type = HCI_ACLDATA_PKT;
pass_up = 1;
} else if ((h5->rx_skb->data[1] & 0x0f) == 4 &&
h5->rx_skb->data[0] & 0x80) {
bt_cb(h5->rx_skb)->pkt_type = HCI_EVENT_PKT;
pass_up = 1;
} else if ((h5->rx_skb->data[1] & 0x0f) == 3) {
bt_cb(h5->rx_skb)->pkt_type = HCI_SCODATA_PKT;
pass_up = 1;
} else if ((h5->rx_skb->data[1] & 0x0f) == 15 &&
!(h5->rx_skb->data[0] & 0x80)) {
//h5_handle_le_pkt(hu);//Link Establishment Pkt
pass_up = 0;
} else if ((h5->rx_skb->data[1] & 0x0f) == 1 &&
h5->rx_skb->data[0] & 0x80) {
bt_cb(h5->rx_skb)->pkt_type = HCI_COMMAND_PKT;
pass_up = 1;
} else if ((h5->rx_skb->data[1] & 0x0f) == 14) {
bt_cb(h5->rx_skb)->pkt_type = H5_VDRSPEC_PKT;
pass_up = 1;
} else
pass_up = 0;
if (!pass_up) {
/* struct hci_event_hdr hdr; */
u8 desc = (h5->rx_skb->data[1] & 0x0f);
if (desc != H5_ACK_PKT && desc != H5_LE_PKT) {
/* if (hciextn) {
* desc |= 0xc0;
* skb_pull(h5->rx_skb, 4);
* memcpy(skb_push(h5->rx_skb, 1), &desc, 1);
* hdr.evt = 0xff;
* hdr.plen = h5->rx_skb->len;
* memcpy(skb_push(h5->rx_skb, HCI_EVENT_HDR_SIZE),
* &hdr, HCI_EVENT_HDR_SIZE);
* bt_cb(h5->rx_skb)->pkt_type = HCI_EVENT_PKT;
* hci_recv_frame(h5->rx_skb);
* } else { */
BT_ERR("Packet for unknown channel (%u %s)",
h5->rx_skb->data[1] & 0x0f,
h5->rx_skb->data[0] & 0x80 ?
"reliable" : "unreliable");
kfree_skb(h5->rx_skb);
/* } */
} else
kfree_skb(h5->rx_skb);
} else {
/* Pull out H5 hdr */
skb_pull(h5->rx_skb, 4);
#ifdef BTCOEX
if (bt_cb(h5->rx_skb)->pkt_type == HCI_EVENT_PKT)
rtk_btcoex_parse_event(h5->rx_skb->data,
h5->rx_skb->len);
if (bt_cb(h5->rx_skb)->pkt_type == HCI_ACLDATA_PKT)
rtk_btcoex_parse_l2cap_data_rx(h5->rx_skb->data,
h5->rx_skb->len);
#endif
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
hci_recv_frame(h5->rx_skb);
#else
hci_recv_frame(hu->hdev, h5->rx_skb);
#endif
}
h5->rx_state = H5_W4_PKT_DELIMITER;
h5->rx_skb = NULL;
}
static u16 bscp_get_crc(struct h5_struct *h5) {
return get_unaligned_be16(&h5->rx_skb->
data[h5->rx_skb->len - 2]);
}
/* Recv data */
static int h5_recv(struct hci_uart *hu, void *data, int count)
{
struct h5_struct *h5 = hu->priv;
register unsigned char *ptr;
u8 rxseq;
unsigned long flags;
BT_DBG("hu %p count %d rx_state %d rx_count %ld",
hu, count, h5->rx_state, h5->rx_count);
ptr = data;
while (count) {
if (h5->rx_count) {
if (*ptr == 0xc0) {
BT_ERR("Short H5 packet");
kfree_skb(h5->rx_skb);
h5->rx_state = H5_W4_PKT_START;
h5->rx_count = 0;
} else
h5_unslip_one_byte(h5, *ptr);
ptr++;
count--;
continue;
}
switch (h5->rx_state) {
case H5_W4_HDR:
if ((0xff & (u8) ~
(h5->rx_skb->data[0] +
h5->rx_skb->data[1] +
h5->rx_skb->data[2])) != h5->rx_skb->data[3]) {
BT_ERR("Error in H5 hdr checksum");
kfree_skb(h5->rx_skb);
h5->rx_state = H5_W4_PKT_DELIMITER;
h5->rx_count = 0;
continue;
}
rxseq = h5->rxseq_txack;
if (h5->rx_skb->data[0] & 0x80 /* reliable pkt */
&& (h5->rx_skb->data[0] & 0x07) != rxseq) {
BT_ERR("Out-of-order packet arrived, got %u expected %u",
h5->rx_skb->data[0] & 0x07, rxseq);
spin_lock_irqsave(&h5->lock, flags);
h5->txack_req = 1;
spin_unlock_irqrestore(&h5->lock, flags);
hci_uart_tx_wakeup(hu);
kfree_skb(h5->rx_skb);
h5->rx_state = H5_W4_PKT_DELIMITER;
h5->rx_count = 0;
continue;
}
h5->rx_state = H5_W4_DATA;
h5->rx_count = (h5->rx_skb->data[1] >> 4) + (h5->rx_skb->data[2] << 4); /* May be 0 */
continue;
case H5_W4_DATA:
if (h5->rx_skb->data[0] & 0x40) { /* pkt with crc */
h5->rx_state = H5_W4_CRC;
h5->rx_count = 2;
} else
h5_complete_rx_pkt(hu);
continue;
case H5_W4_CRC:
if (bitrev16(h5->message_crc) != bscp_get_crc(h5)) {
BT_ERR
("Checksum failed: computed %04x received %04x",
bitrev16(h5->message_crc),
bscp_get_crc(h5));
kfree_skb(h5->rx_skb);
h5->rx_state = H5_W4_PKT_DELIMITER;
h5->rx_count = 0;
continue;
}
skb_trim(h5->rx_skb, h5->rx_skb->len - 2);
h5_complete_rx_pkt(hu);
continue;
case H5_W4_PKT_DELIMITER:
switch (*ptr) {
case 0xc0:
h5->rx_state = H5_W4_PKT_START;
break;
default:
/*BT_ERR("Ignoring byte %02x", *ptr); */
break;
}
ptr++;
count--;
break;
case H5_W4_PKT_START:
switch (*ptr) {
case 0xc0:
ptr++;
count--;
break;
default:
h5->rx_state = H5_W4_HDR;
h5->rx_count = 4;
h5->rx_esc_state = H5_ESCSTATE_NOESC;
H5_CRC_INIT(h5->message_crc);
/* Do not increment ptr or decrement count
* Allocate packet. Max len of a H5 pkt=
* 0xFFF (payload) +4 (header) +2 (crc) */
h5->rx_skb = bt_skb_alloc(0x1005, GFP_ATOMIC);
if (!h5->rx_skb) {
BT_ERR
("Can't allocate mem for new packet");
h5->rx_state = H5_W4_PKT_DELIMITER;
h5->rx_count = 0;
return 0;
}
h5->rx_skb->dev = (void *)hu->hdev;
break;
}
break;
}
}
return count;
}
/* Arrange to retransmit all messages in the relq. */
static void h5_timed_event(struct work_struct *work)
{
struct h5_struct *h5;
struct hci_uart *hu;
unsigned long flags;
unsigned long flags2;
struct sk_buff *skb;
h5 = container_of(work, struct h5_struct, retrans_work.work);
hu = h5->hu;
BT_INFO("hu %p retransmitting %u pkts", hu, h5->unack.qlen);
spin_lock_irqsave_nested(&h5->unack.lock, flags, SINGLE_DEPTH_NESTING);
/* Move the pkt from unack queue to the head of reliable tx queue and
* roll back the tx seq number
*/
while ((skb = __skb_dequeue_tail(&h5->unack)) != NULL) {
spin_lock_irqsave(&h5->lock, flags2);
h5->msgq_txseq = (h5->msgq_txseq - 1) & 0x07;
spin_unlock_irqrestore(&h5->lock, flags2);
skb_queue_head(&h5->rel, skb);
}
spin_unlock_irqrestore(&h5->unack.lock, flags);
hci_uart_tx_wakeup(hu);
}
static int h5_open(struct hci_uart *hu)
{
struct h5_struct *h5;
BT_DBG("hu %p", hu);
BT_INFO("h5_open");
h5 = kzalloc(sizeof(*h5), GFP_ATOMIC);
if (!h5)
return -ENOMEM;
hu->priv = h5;
skb_queue_head_init(&h5->unack);
skb_queue_head_init(&h5->rel);
skb_queue_head_init(&h5->unrel);
spin_lock_init(&h5->lock);
h5->hu = hu;
INIT_DELAYED_WORK(&h5->retrans_work, (void *)h5_timed_event);
h5->rx_state = H5_W4_PKT_DELIMITER;
if (txcrc)
h5->use_crc = 1;
return 0;
}
static int h5_close(struct hci_uart *hu)
{
struct h5_struct *h5 = hu->priv;
BT_INFO("h5_close");
cancel_delayed_work_sync(&h5->retrans_work);
hu->priv = NULL;
skb_queue_purge(&h5->unack);
skb_queue_purge(&h5->rel);
skb_queue_purge(&h5->unrel);
kfree(h5);
return 0;
}
static struct hci_uart_proto h5 = {
.id = HCI_UART_3WIRE,
.open = h5_open,
.close = h5_close,
.enqueue = h5_enqueue,
.dequeue = h5_dequeue,
.recv = h5_recv,
.flush = h5_flush
};
int h5_init(void)
{
int err = hci_uart_register_proto(&h5);
if (!err)
BT_INFO("HCI Realtek H5 protocol initialized");
else
BT_ERR("HCI Realtek H5 protocol registration failed");
return err;
}
int h5_deinit(void)
{
return hci_uart_unregister_proto(&h5);
}

View File

@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
*
* Bluetooth HCI UART driver
@@ -5,50 +6,12 @@
* Copyright (C) 2000-2001 Qualcomm Incorporated
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/version.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
/* #define HCI_VERSION_CODE KERNEL_VERSION(3, 14, 41) */
#define HCI_VERSION_CODE LINUX_VERSION_CODE
#ifndef N_HCI
#define N_HCI 15
#endif
#ifndef CONFIG_BT_HCIUART_H4
#define CONFIG_BT_HCIUART_H4
#endif
#define BTCOEX
/* Send host sleep notification to Controller */
#define WOBT_NOTIFY 0 /* 1 enable; 0 disable */
/* Send LE whitelist only for Background scan parameters */
#define WOBT_NOTIFY_BG_SCAN_LE_WHITELIST_ONLY (0 * WOBT_NOTIFY) /* 1 enable; 0 disable */
/* RTKBT Power-on Whitelist for sideband wake-up by LE Advertising from Remote.
* Note that it's necessary to apply TV FW Patch. */
#define RTKBT_TV_POWERON_WHITELIST (0 * WOBT_NOTIFY) /* 1 enable; 0 disable */
/* Ioctls */
#define HCIUARTSETPROTO _IOW('U', 200, int)
#define HCIUARTGETPROTO _IOR('U', 201, int)
@@ -57,7 +20,7 @@
#define HCIUARTGETFLAGS _IOR('U', 204, int)
/* UART protocols */
#define HCI_UART_MAX_PROTO 6
#define HCI_UART_MAX_PROTO 12
#define HCI_UART_H4 0
#define HCI_UART_BCSP 1
@@ -65,6 +28,12 @@
#define HCI_UART_H4DS 3
#define HCI_UART_LL 4
#define HCI_UART_ATH3K 5
#define HCI_UART_INTEL 6
#define HCI_UART_BCM 7
#define HCI_UART_QCA 8
#define HCI_UART_AG6XX 9
#define HCI_UART_NOKIA 10
#define HCI_UART_MRVL 11
#define HCI_UART_RAW_DEVICE 0
#define HCI_UART_RESET_ON_INIT 1
@@ -74,42 +43,46 @@
#define HCI_UART_VND_DETECT 5
struct hci_uart;
struct serdev_device;
struct hci_uart_proto {
unsigned int id;
const char *name;
unsigned int manufacturer;
unsigned int init_speed;
unsigned int oper_speed;
int (*open)(struct hci_uart *hu);
int (*close)(struct hci_uart *hu);
int (*flush)(struct hci_uart *hu);
int (*recv)(struct hci_uart *hu, void *data, int len);
int (*setup)(struct hci_uart *hu);
int (*set_baudrate)(struct hci_uart *hu, unsigned int speed);
int (*recv)(struct hci_uart *hu, const void *data, int len);
int (*enqueue)(struct hci_uart *hu, struct sk_buff *skb);
struct sk_buff *(*dequeue)(struct hci_uart *hu);
};
struct hci_uart {
struct tty_struct *tty;
struct serdev_device *serdev;
struct hci_dev *hdev;
unsigned long flags;
unsigned long hdev_flags;
struct work_struct init_ready;
struct work_struct write_work;
struct workqueue_struct *hci_uart_wq;
struct hci_uart_proto *proto;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
struct percpu_rw_semaphore proto_lock; /* Stop work for proto close */
#else
struct rw_semaphore proto_lock;
#endif
const struct hci_uart_proto *proto;
struct percpu_rw_semaphore proto_lock; /* Stop work for proto close */
void *priv;
struct semaphore tx_sem; /* semaphore for tx */
struct sk_buff *tx_skb;
unsigned long tx_state;
#if WOBT_NOTIFY
struct notifier_block pm_notify_block;
#endif
unsigned int init_speed;
unsigned int oper_speed;
u8 alignment;
u8 padding;
};
/* HCI_UART proto flag bits */
@@ -121,20 +94,108 @@ struct hci_uart {
#define HCI_UART_SENDING 1
#define HCI_UART_TX_WAKEUP 2
extern int hci_uart_register_proto(struct hci_uart_proto *p);
extern int hci_uart_unregister_proto(struct hci_uart_proto *p);
extern int hci_uart_tx_wakeup(struct hci_uart *hu);
int hci_uart_register_proto(const struct hci_uart_proto *p);
int hci_uart_unregister_proto(const struct hci_uart_proto *p);
int hci_uart_register_device(struct hci_uart *hu, const struct hci_uart_proto *p);
void hci_uart_unregister_device(struct hci_uart *hu);
int hci_uart_tx_wakeup(struct hci_uart *hu);
int hci_uart_wait_until_sent(struct hci_uart *hu);
int hci_uart_init_ready(struct hci_uart *hu);
void hci_uart_init_work(struct work_struct *work);
void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed);
bool hci_uart_has_flow_control(struct hci_uart *hu);
void hci_uart_set_flow_control(struct hci_uart *hu, bool enable);
void hci_uart_set_speeds(struct hci_uart *hu, unsigned int init_speed,
unsigned int oper_speed);
#ifdef CONFIG_BT_HCIUART_H4
extern int h4_init(void);
extern int h4_deinit(void);
int h4_init(void);
int h4_deinit(void);
struct h4_recv_pkt {
u8 type; /* Packet type */
u8 hlen; /* Header length */
u8 loff; /* Data length offset in header */
u8 lsize; /* Data length field size */
u16 maxlen; /* Max overall packet length */
int (*recv)(struct hci_dev *hdev, struct sk_buff *skb);
};
#define H4_RECV_ACL \
.type = HCI_ACLDATA_PKT, \
.hlen = HCI_ACL_HDR_SIZE, \
.loff = 2, \
.lsize = 2, \
.maxlen = HCI_MAX_FRAME_SIZE \
#define H4_RECV_SCO \
.type = HCI_SCODATA_PKT, \
.hlen = HCI_SCO_HDR_SIZE, \
.loff = 2, \
.lsize = 1, \
.maxlen = HCI_MAX_SCO_SIZE
#define H4_RECV_EVENT \
.type = HCI_EVENT_PKT, \
.hlen = HCI_EVENT_HDR_SIZE, \
.loff = 1, \
.lsize = 1, \
.maxlen = HCI_MAX_EVENT_SIZE
#define H4_RECV_ISO \
.type = HCI_ISODATA_PKT, \
.hlen = HCI_ISO_HDR_SIZE, \
.loff = 2, \
.lsize = 2, \
.maxlen = HCI_MAX_FRAME_SIZE \
struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
const unsigned char *buffer, int count,
const struct h4_recv_pkt *pkts, int pkts_count);
#endif
extern int h5_init(void);
extern int h5_deinit(void);
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
extern int hci_uart_send_frame(struct sk_buff *skb);
#else
extern int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb);
#ifdef CONFIG_BT_HCIUART_BCSP
int bcsp_init(void);
int bcsp_deinit(void);
#endif
#ifdef CONFIG_BT_HCIUART_LL
int ll_init(void);
int ll_deinit(void);
#endif
#ifdef CONFIG_BT_HCIUART_ATH3K
int ath_init(void);
int ath_deinit(void);
#endif
#ifdef CONFIG_BT_HCIUART_3WIRE
int h5_init(void);
int h5_deinit(void);
#endif
#ifdef CONFIG_BT_HCIUART_INTEL
int intel_init(void);
int intel_deinit(void);
#endif
#ifdef CONFIG_BT_HCIUART_BCM
int bcm_init(void);
int bcm_deinit(void);
#endif
#ifdef CONFIG_BT_HCIUART_QCA
int qca_init(void);
int qca_deinit(void);
#endif
#ifdef CONFIG_BT_HCIUART_AG6XX
int ag6xx_init(void);
int ag6xx_deinit(void);
#endif
#ifdef CONFIG_BT_HCIUART_MRVL
int mrvl_init(void);
int mrvl_deinit(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,373 +0,0 @@
/*
*
* Realtek Bluetooth USB driver
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <net/bluetooth/hci_core.h>
#include <linux/list.h>
/***********************************
** Realtek - For coexistence **
***********************************/
#define BTRTL_HCIUSB 0
#define BTRTL_HCIUART 1
#define BTRTL_HCI_IF BTRTL_HCIUART
#define TRUE 1
#define FALSE 0
#define CONNECT_PORT 30001
#define CONNECT_PORT_WIFI 30000
#define invite_req "INVITE_REQ"
#define invite_rsp "INVITE_RSP"
#define attend_req "ATTEND_REQ"
#define attend_ack "ATTEND_ACK"
#define wifi_leave "WIFI_LEAVE"
#define leave_ack "LEAVE_ACK"
#define bt_leave "BT_LEAVE"
#define HCI_OP_PERIODIC_INQ 0x0403
#define HCI_EV_LE_META 0x3e
#define HCI_EV_LE_CONN_COMPLETE 0x01
#define HCI_EV_LE_CONN_UPDATE_COMPLETE 0x03
#define HCI_EV_LE_ENHANCED_CONN_COMPLETE 0x0a
//vendor cmd to fw
#define HCI_VENDOR_ENABLE_PROFILE_REPORT_COMMAND 0xfc18
#define HCI_VENDOR_SET_PROFILE_REPORT_COMMAND 0xfc19
#define HCI_VENDOR_MAILBOX_CMD 0xfc8f
#define HCI_VENDOR_SET_BITPOOL 0xfc51
//subcmd to fw
#define HCI_VENDOR_SUB_CMD_WIFI_CHANNEL_AND_BANDWIDTH_CMD 0x11
#define HCI_VENDOR_SUB_CMD_WIFI_FORCE_TX_POWER_CMD 0x17
#define HCI_VENDOR_SUB_CMD_BT_ENABLE_IGNORE_WLAN_ACT_CMD 0x1B
#define HCI_VENDOR_SUB_CMD_BT_REPORT_CONN_SCO_INQ_INFO 0x23
#define HCI_VENDOR_SUB_CMD_BT_AUTO_REPORT_STATUS_INFO 0x27
#define HCI_VENDOR_SUB_CMD_BT_AUTO_REPORT_ENABLE 0x28
#define HCI_VENDOR_SUB_CMD_BT_SET_TXRETRY_REPORT_PARAM 0x29
#define HCI_VENDOR_SUB_CMD_BT_SET_PTATABLE 0x2A
#define HCI_VENDOR_SUB_CMD_SET_BT_PSD_MODE 0x31
#define HCI_VENDOR_SUB_CMD_SET_BT_LNA_CONSTRAINT 0x32
#define HCI_VENDOR_SUB_CMD_GET_AFH_MAP_L 0x40
#define HCI_VENDOR_SUB_CMD_GET_AFH_MAP_M 0x41
#define HCI_VENDOR_SUB_CMD_GET_AFH_MAP_H 0x42
#define HCI_VENDOR_SUB_CMD_RD_REG_REQ 0x43
#define HCI_VENDOR_SUB_CMD_WR_REG_REQ 0x44
#define HCI_EV_VENDOR_SPECIFIC 0xff
//sub event from fw start
#define HCI_VENDOR_PTA_REPORT_EVENT 0x24
#define HCI_VENDOR_PTA_AUTO_REPORT_EVENT 0x25
//vendor cmd to wifi driver
#define HCI_GRP_VENDOR_SPECIFIC (0x3f << 10)
#define HCI_OP_HCI_EXTENSION_VERSION_NOTIFY (0x0100 | HCI_GRP_VENDOR_SPECIFIC)
#define HCI_OP_BT_OPERATION_NOTIFY (0x0102 | HCI_GRP_VENDOR_SPECIFIC)
#define HCI_OP_HCI_BT_INFO_NOTIFY (0x0106 | HCI_GRP_VENDOR_SPECIFIC)
#define HCI_OP_HCI_BT_COEX_NOTIFY (0x0107 | HCI_GRP_VENDOR_SPECIFIC)
#define HCI_OP_HCI_BT_PATCH_VER_NOTIFY (0x0108 | HCI_GRP_VENDOR_SPECIFIC)
#define HCI_OP_HCI_BT_AFH_MAP_NOTIFY (0x0109 | HCI_GRP_VENDOR_SPECIFIC)
#define HCI_OP_HCI_BT_REGISTER_VALUE_NOTIFY (0x010a | HCI_GRP_VENDOR_SPECIFIC)
//bt info reason to wifi
#define HOST_RESPONSE 0 //Host response when receive the BT Info Control Event
#define POLLING_RESPONSE 1 //The BT Info response for polling by BT firmware.
#define AUTO_REPORT 2 //BT auto report by BT firmware.
#define STACK_REPORT_WHILE_DEVICE_D2 3 //Stack report when BT firmware is under power save state(ex:D2)
// vendor event from wifi
#define RTK_HS_EXTENSION_EVENT_WIFI_SCAN 0x01
#define RTK_HS_EXTENSION_EVENT_RADIO_STATUS_NOTIFY 0x02
#define RTK_HS_EXTENSION_EVENT_HCI_BT_INFO_CONTROL 0x03
#define RTK_HS_EXTENSION_EVENT_HCI_BT_COEX_CONTROL 0x04
//op code from wifi
#define BT_PATCH_VERSION_QUERY 0x00
#define IGNORE_WLAN_ACTIVE_CONTROL 0x01
#define LNA_CONSTRAIN_CONTROL 0x02
#define BT_POWER_DECREASE_CONTROL 0x03
#define BT_PSD_MODE_CONTROL 0x04
#define WIFI_BW_CHNL_NOTIFY 0x05
#define QUERY_BT_AFH_MAP 0x06
#define BT_REGISTER_ACCESS 0x07
//bt operation to notify
#define BT_OPCODE_NONE 0
#define BT_OPCODE_INQUIRY_START 1
#define BT_OPCODE_INQUIRY_END 2
#define BT_OPCODE_PAGE_START 3
#define BT_OPCODE_PAGE_SUCCESS_END 4
#define BT_OPCODE_PAGE_UNSUCCESS_END 5
#define BT_OPCODE_PAIR_START 6
#define BT_OPCODE_PAIR_END 7
#define BT_OPCODE_ENABLE_BT 8
#define BT_OPCODE_DISABLE_BT 9
#define HCI_EXTENSION_VERSION 0x0004
#define HCI_CMD_PREAMBLE_SIZE 3
#define PAN_PACKET_COUNT 5
#define STREAM_TO_UINT16(u16, p) {u16 = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); (p) += 2;}
#define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);}
#define PSM_SDP 0x0001
#define PSM_RFCOMM 0x0003
#define PSM_PAN 0x000F
#define PSM_HID 0x0011
#define PSM_HID_INT 0x0013
#define PSM_AVCTP 0x0017
#define PSM_AVDTP 0x0019
#define PSM_FTP 0x1001
#define PSM_BIP 0x1003
#define PSM_OPP 0x1015
//--add more if needed--//
enum {
profile_sco = 0,
profile_hid = 1,
profile_a2dp = 2,
profile_pan = 3,
profile_hid_interval = 4,
profile_hogp = 5,
profile_voice = 6,
profile_sink = 7,
profile_max = 8
};
#define A2DP_SIGNAL 0x01
#define A2DP_MEDIA 0x02
//profile info data
typedef struct {
struct list_head list;
uint16_t handle;
uint16_t psm;
uint16_t dcid;
uint16_t scid;
uint8_t profile_index;
uint8_t flags;
} rtk_prof_info, *prtk_prof_info;
//profile info for each connection
typedef struct rtl_hci_conn {
struct list_head list;
uint16_t handle;
uint8_t type; // 0:l2cap, 1:sco/esco, 2:le
uint8_t profile_bitmap;
int8_t profile_refcount[8];
} rtk_conn_prof, *prtk_conn_prof;
#ifdef RTB_SOFTWARE_MAILBOX
struct rtl_btinfo {
u8 cmd;
u8 len;
u8 data[6];
};
#define RTL_BTINFO_LEN (sizeof(struct rtl_btinfo))
/* typedef struct {
* uint8_t cmd_index;
* uint8_t cmd_length;
* uint8_t link_status;
* uint8_t retry_cnt;
* uint8_t rssi;
* uint8_t mailbox_info;
* uint16_t acl_throughput;
* } hci_linkstatus_report; */
typedef struct {
uint8_t type;
uint32_t offset;
uint32_t value;
} hci_mailbox_register;
struct rtl_btinfo_ctl {
uint8_t polling_enable;
uint8_t polling_time;
uint8_t autoreport_enable;
};
#endif /* RTB_SOFTWARE_MAILBOX */
#define MAX_LEN_OF_HCI_EV 32
#define NUM_RTL_HCI_EV 32
struct rtl_hci_ev {
__u8 data[MAX_LEN_OF_HCI_EV];
__u16 len;
struct list_head list;
};
#define L2_MAX_SUBSEC_LEN 128
#define L2_MAX_PKTS 16
struct rtl_l2_buff {
__u8 data[L2_MAX_SUBSEC_LEN];
__u16 len;
__u16 out;
struct list_head list;
};
struct rtl_coex_struct {
struct list_head conn_hash; //hash for connections
struct list_head profile_list; //hash for profile info
struct hci_dev *hdev;
#ifdef RTB_SOFTWARE_MAILBOX
struct socket *udpsock;
struct sockaddr_in addr;
struct sockaddr_in wifi_addr;
struct timer_list polling_timer;
#endif
struct timer_list a2dp_count_timer;
struct timer_list pan_count_timer;
struct timer_list hogp_count_timer;
#ifdef RTB_SOFTWARE_MAILBOX
struct workqueue_struct *sock_wq;
struct delayed_work sock_work;
#endif
struct workqueue_struct *fw_wq;
struct delayed_work fw_work;
struct delayed_work l2_work;
#ifdef RTB_SOFTWARE_MAILBOX
struct sock *sk;
#endif
struct urb *urb;
spinlock_t spin_lock_sock;
spinlock_t spin_lock_profile;
uint32_t a2dp_packet_count;
uint32_t pan_packet_count;
uint32_t hogp_packet_count;
uint32_t voice_packet_count;
uint8_t profile_bitmap;
uint8_t profile_status;
int8_t profile_refcount[8];
uint8_t ispairing;
uint8_t isinquirying;
uint8_t ispaging;
#ifdef RTB_SOFTWARE_MAILBOX
uint8_t wifi_state;
uint8_t autoreport;
uint8_t polling_enable;
uint8_t polling_interval;
uint8_t piconet_id;
uint8_t mode;
uint8_t afh_map[10];
#endif
uint16_t hci_reversion;
uint16_t lmp_subversion;
#ifdef RTB_SOFTWARE_MAILBOX
uint8_t wifi_on;
uint8_t sock_open;
#endif
unsigned long cmd_last_tx;
/* hci ev buff */
struct list_head ev_used_list;
struct list_head ev_free_list;
spinlock_t rxlock;
__u8 pkt_type;
__u16 expect;
__u8 *tbuff;
__u16 elen;
__u8 back_buff[HCI_MAX_EVENT_SIZE];
/* l2cap rx buff */
struct list_head l2_used_list;
struct list_head l2_free_list;
/* buff addr and size */
spinlock_t buff_lock;
unsigned long pages_addr;
unsigned long buff_size;
#define RTL_COEX_RUNNING (1 << 0)
unsigned long flags;
};
#ifdef __LITTLE_ENDIAN
struct sbc_frame_hdr {
uint8_t syncword:8; /* Sync word */
uint8_t subbands:1; /* Subbands */
uint8_t allocation_method:1; /* Allocation method */
uint8_t channel_mode:2; /* Channel mode */
uint8_t blocks:2; /* Blocks */
uint8_t sampling_frequency:2; /* Sampling frequency */
uint8_t bitpool:8; /* Bitpool */
uint8_t crc_check:8; /* CRC check */
} __attribute__ ((packed));
/* NOTE: The code is copied from pa.
* only the bit field in 8-bit is affected by endian, not the 16-bit or 32-bit.
* why?
*/
struct rtp_header {
unsigned cc:4;
unsigned x:1;
unsigned p:1;
unsigned v:2;
unsigned pt:7;
unsigned m:1;
uint16_t sequence_number;
uint32_t timestamp;
uint32_t ssrc;
uint32_t csrc[0];
} __attribute__ ((packed));
#else
/* big endian */
struct sbc_frame_hdr {
uint8_t syncword:8; /* Sync word */
uint8_t sampling_frequency:2; /* Sampling frequency */
uint8_t blocks:2; /* Blocks */
uint8_t channel_mode:2; /* Channel mode */
uint8_t allocation_method:1; /* Allocation method */
uint8_t subbands:1; /* Subbands */
uint8_t bitpool:8; /* Bitpool */
uint8_t crc_check:8; /* CRC check */
} __attribute__ ((packed));
struct rtp_header {
unsigned v:2;
unsigned p:1;
unsigned x:1;
unsigned cc:4;
unsigned m:1;
unsigned pt:7;
uint16_t sequence_number;
uint32_t timestamp;
uint32_t ssrc;
uint32_t csrc[0];
} __attribute__ ((packed));
#endif /* __LITTLE_ENDIAN */
void rtk_btcoex_parse_event(uint8_t *buffer, int count);
void rtk_btcoex_parse_cmd(uint8_t *buffer, int count);
void rtk_btcoex_parse_l2cap_data_tx(uint8_t *buffer, int count);
void rtk_btcoex_parse_l2cap_data_rx(uint8_t *buffer, int count);
void rtk_btcoex_open(struct hci_dev *hdev);
void rtk_btcoex_close(void);
void rtk_btcoex_probe(struct hci_dev *hdev);
void rtk_btcoex_init(void);
void rtk_btcoex_exit(void);

View File

@@ -1947,6 +1947,7 @@ _SetHardwareOptions(
gcmkASSERT(gcvSTATUS_TRUE == gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_SECURITY_AHB));
options->secureMode = gcvSECURE_IN_NORMAL;
pr_err("gcvSECURE_IN_NORMAL because of SECURITY\n");
status = gckOS_QueryOption(Hardware->os, "TA", &data);
@@ -1958,6 +1959,7 @@ _SetHardwareOptions(
else if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_SECURITY_AHB))
{
options->secureMode = gcvSECURE_IN_NORMAL;
pr_err("gcvSECURE_IN_NORMAL because of SECURITY_AHB\n");
}
options->hasShader = database->NumShaderCores;

View File

@@ -25,7 +25,7 @@ struct c910_priv {
static gcsPLATFORM c910_platform;
static const struct of_device_id c910_gc620_dt_ids[] = {
{ .compatible = "thead,c910-gc620", },
{ .compatible = "vivante,gc", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, c910_gc620_dt_ids);
@@ -37,7 +37,7 @@ static gceSTATUS c910_adjustParam(IN gcsPLATFORM * Platform,
struct resource *res;
struct platform_device *pdev = Platform->device;
irq = platform_get_irq_byname(pdev, "irq_2d");
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return gcvSTATUS_NOT_FOUND;
@@ -58,15 +58,15 @@ static gceSTATUS c910_getPower(IN gcsPLATFORM * Platform)
struct c910_priv *c910 = Platform->priv;
struct platform_device *pdev = c910_platform.device;
c910->pclk = devm_clk_get(&pdev->dev, "pclk");
c910->pclk = devm_clk_get(&pdev->dev, "bus");
if (IS_ERR(c910->pclk))
return gcvSTATUS_NOT_FOUND;
c910->aclk = devm_clk_get(&pdev->dev, "aclk");
c910->aclk = devm_clk_get(&pdev->dev, "core");
if (IS_ERR(c910->aclk))
return gcvSTATUS_NOT_FOUND;
c910->cclk = devm_clk_get(&pdev->dev, "cclk");
c910->cclk = devm_clk_get(&pdev->dev, "shader");
if (IS_ERR(c910->cclk))
return gcvSTATUS_NOT_FOUND;
@@ -118,7 +118,7 @@ int gckPLATFORM_Init(struct platform_driver *pdrv, gcsPLATFORM **platform)
struct platform_device *pdev;
struct c910_priv *c910;
np = of_find_compatible_node(NULL, NULL, "thead,c910-gc620");
np = of_find_compatible_node(NULL, NULL, "vivante,gc");
if (!np)
return -ENODEV;
of_node_put(np);

View File

@@ -65,6 +65,7 @@ DEALINGS IN THE SOFTWARE.
#define chipModel_GC520 0x00000520
#define chipModel_GC530 0x00000530
#define chipModel_GC600 0x00000600
#define chipModel_GC620 0x00000620
#define chipModel_GC700 0x00000700
#define chipModel_GC800 0x00000800
#define chipModel_GC860 0x00000860

View File

@@ -53,11 +53,12 @@ static inline void CMD_END(struct etnaviv_cmdbuf *buffer)
OUT(buffer, VIV_FE_END_HEADER_OP_END);
}
static inline void CMD_WAIT(struct etnaviv_cmdbuf *buffer)
static inline void CMD_WAIT(struct etnaviv_cmdbuf *buffer,
unsigned int waitcycles)
{
buffer->user_size = ALIGN(buffer->user_size, 8);
OUT(buffer, VIV_FE_WAIT_HEADER_OP_WAIT | 200);
OUT(buffer, VIV_FE_WAIT_HEADER_OP_WAIT | waitcycles);
}
static inline void CMD_LINK(struct etnaviv_cmdbuf *buffer,
@@ -168,7 +169,7 @@ u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
/* initialize buffer */
buffer->user_size = 0;
CMD_WAIT(buffer);
CMD_WAIT(buffer, gpu->fe_waitcycles);
CMD_LINK(buffer, 2,
etnaviv_cmdbuf_get_va(buffer, &gpu->mmu_context->cmdbuf_mapping)
+ buffer->user_size - 4);
@@ -320,7 +321,7 @@ void etnaviv_sync_point_queue(struct etnaviv_gpu *gpu, unsigned int event)
CMD_END(buffer);
/* Append waitlink */
CMD_WAIT(buffer);
CMD_WAIT(buffer, gpu->fe_waitcycles);
CMD_LINK(buffer, 2,
etnaviv_cmdbuf_get_va(buffer, &gpu->mmu_context->cmdbuf_mapping)
+ buffer->user_size - 4);
@@ -416,8 +417,11 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
if (switch_mmu_context &&
gpu->sec_mode == ETNA_SEC_KERNEL) {
unsigned short id =
etnaviv_iommuv2_get_pta_id(gpu->mmu_context);
unsigned short id;
etnaviv_iommuv2_update_pta_entry(gpu->mmu_context);
id = etnaviv_iommuv2_get_pta_id(gpu->mmu_context);
CMD_LOAD_STATE(buffer,
VIVS_MMUv2_PTA_CONFIG,
VIVS_MMUv2_PTA_CONFIG_INDEX(id));
@@ -503,7 +507,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) |
VIVS_GL_EVENT_FROM_PE);
CMD_WAIT(buffer);
CMD_WAIT(buffer, gpu->fe_waitcycles);
CMD_LINK(buffer, 2,
etnaviv_cmdbuf_get_va(buffer, &gpu->mmu_context->cmdbuf_mapping)
+ buffer->user_size - 4);

View File

@@ -121,6 +121,9 @@ void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf)
int order = order_base_2(ALIGN(cmdbuf->size, SUBALLOC_GRANULE) /
SUBALLOC_GRANULE);
if (!suballoc)
return;
mutex_lock(&suballoc->lock);
bitmap_release_region(suballoc->granule_map,
cmdbuf->suballoc_offset / SUBALLOC_GRANULE,

View File

@@ -468,12 +468,6 @@ static const struct drm_ioctl_desc etnaviv_ioctls[] = {
ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_RENDER_ALLOW),
};
static const struct vm_operations_struct vm_ops = {
.fault = etnaviv_gem_fault,
.open = drm_gem_vm_open,
.close = drm_gem_vm_close,
};
static const struct file_operations fops = {
.owner = THIS_MODULE,
.open = drm_open,
@@ -490,16 +484,9 @@ static struct drm_driver etnaviv_drm_driver = {
.driver_features = DRIVER_GEM | DRIVER_RENDER,
.open = etnaviv_open,
.postclose = etnaviv_postclose,
.gem_free_object_unlocked = etnaviv_gem_free_object,
.gem_vm_ops = &vm_ops,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_pin = etnaviv_gem_prime_pin,
.gem_prime_unpin = etnaviv_gem_prime_unpin,
.gem_prime_get_sg_table = etnaviv_gem_prime_get_sg_table,
.gem_prime_import_sg_table = etnaviv_gem_prime_import_sg_table,
.gem_prime_vmap = etnaviv_gem_prime_vmap,
.gem_prime_vunmap = etnaviv_gem_prime_vunmap,
.gem_prime_mmap = etnaviv_gem_prime_mmap,
#ifdef CONFIG_DEBUG_FS
.debugfs_init = etnaviv_debugfs_init,
@@ -685,8 +672,24 @@ static int __init etnaviv_init(void)
of_node_put(np);
goto unregister_platform_driver;
}
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(40);
pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
/*
* PTA and MTLB can have 40 bit base addresses, but
* unfortunately, an entry in the MTLB can only point to a
* 32 bit base address of a STLB. Moreover, to initialize the
* MMU we need a command buffer with a 32 bit address because
* without an MMU there is only an indentity mapping between
* the internal 32 bit addresses and the bus addresses.
*
* To make things easy, we set the dma_coherent_mask to 32
* bit to make sure we are allocating the command buffers and
* TLBs in the lower 4 GiB address space.
*/
if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)) ||
dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32))) {
dev_dbg(&pdev->dev, "No suitable DMA available\n");
return -ENODEV;
}
/*
* Apply the same DMA configuration to the virtual etnaviv

View File

@@ -49,7 +49,6 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
struct drm_file *file);
int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma);
vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf);
int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset);
struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj);
void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj);

View File

@@ -125,9 +125,9 @@ void etnaviv_core_dump(struct etnaviv_gem_submit *submit)
return;
etnaviv_dump_core = false;
mutex_lock(&gpu->mmu_context->lock);
mutex_lock(&submit->mmu_context->lock);
mmu_size = etnaviv_iommu_dump_size(gpu->mmu_context);
mmu_size = etnaviv_iommu_dump_size(submit->mmu_context);
/* We always dump registers, mmu, ring, hanging cmdbuf and end marker */
n_obj = 5;
@@ -157,7 +157,7 @@ void etnaviv_core_dump(struct etnaviv_gem_submit *submit)
iter.start = __vmalloc(file_size, GFP_KERNEL | __GFP_NOWARN |
__GFP_NORETRY);
if (!iter.start) {
mutex_unlock(&gpu->mmu_context->lock);
mutex_unlock(&submit->mmu_context->lock);
dev_warn(gpu->dev, "failed to allocate devcoredump file\n");
return;
}
@@ -169,18 +169,18 @@ void etnaviv_core_dump(struct etnaviv_gem_submit *submit)
memset(iter.hdr, 0, iter.data - iter.start);
etnaviv_core_dump_registers(&iter, gpu);
etnaviv_core_dump_mmu(&iter, gpu->mmu_context, mmu_size);
etnaviv_core_dump_mmu(&iter, submit->mmu_context, mmu_size);
etnaviv_core_dump_mem(&iter, ETDUMP_BUF_RING, gpu->buffer.vaddr,
gpu->buffer.size,
etnaviv_cmdbuf_get_va(&gpu->buffer,
&gpu->mmu_context->cmdbuf_mapping));
&submit->mmu_context->cmdbuf_mapping));
etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD,
submit->cmdbuf.vaddr, submit->cmdbuf.size,
etnaviv_cmdbuf_get_va(&submit->cmdbuf,
&gpu->mmu_context->cmdbuf_mapping));
&submit->mmu_context->cmdbuf_mapping));
mutex_unlock(&gpu->mmu_context->lock);
mutex_unlock(&submit->mmu_context->lock);
/* Reserve space for the bomap */
if (n_bomap_pages) {

View File

@@ -130,8 +130,7 @@ static int etnaviv_gem_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
{
pgprot_t vm_page_prot;
vma->vm_flags &= ~VM_PFNMAP;
vma->vm_flags |= VM_MIXEDMAP;
vma->vm_flags |= VM_PFNMAP;
vm_page_prot = vm_get_page_prot(vma->vm_flags);
@@ -171,12 +170,13 @@ int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma)
return obj->ops->mmap(obj, vma);
}
vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf)
static vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
struct drm_gem_object *obj = vma->vm_private_data;
struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
struct page **pages, *page;
struct page **pages;
unsigned long pfn;
pgoff_t pgoff;
int err;
@@ -200,12 +200,12 @@ vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf)
/* We don't use vmf->pgoff since that has the fake offset: */
pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
page = pages[pgoff];
pfn = page_to_pfn(pages[pgoff]);
VERB("Inserting %p pfn %lx, pa %lx", (void *)vmf->address,
page_to_pfn(page), page_to_pfn(page) << PAGE_SHIFT);
pfn, pfn << PAGE_SHIFT);
return vmf_insert_page(vma, vmf->address, page);
return vmf_insert_pfn(vma, vmf->address, pfn);
}
int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset)
@@ -269,7 +269,12 @@ struct etnaviv_vram_mapping *etnaviv_gem_mapping_get(
if (mapping->use == 0) {
mutex_lock(&mmu_context->lock);
if (mapping->context == mmu_context)
mapping->use += 1;
if (va && mapping->iova != va) {
etnaviv_iommu_reap_mapping(mapping);
mapping = NULL;
} else {
mapping->use += 1;
}
else
mapping = NULL;
mutex_unlock(&mmu_context->lock);
@@ -305,18 +310,15 @@ struct etnaviv_vram_mapping *etnaviv_gem_mapping_get(
list_del(&mapping->obj_node);
}
mapping->context = etnaviv_iommu_context_get(mmu_context);
mapping->use = 1;
ret = etnaviv_iommu_map_gem(mmu_context, etnaviv_obj,
mmu_context->global->memory_base,
mapping, va);
if (ret < 0) {
etnaviv_iommu_context_put(mmu_context);
if (ret < 0)
kfree(mapping);
} else {
else
list_add_tail(&mapping->obj_node, &etnaviv_obj->vram_list);
}
out:
mutex_unlock(&etnaviv_obj->lock);
@@ -532,10 +534,8 @@ void etnaviv_gem_free_object(struct drm_gem_object *obj)
WARN_ON(mapping->use);
if (context) {
if (context)
etnaviv_iommu_unmap_gem(context, mapping);
etnaviv_iommu_context_put(context);
}
list_del(&mapping->obj_node);
kfree(mapping);
@@ -558,6 +558,22 @@ void etnaviv_gem_obj_add(struct drm_device *dev, struct drm_gem_object *obj)
mutex_unlock(&priv->gem_lock);
}
static const struct vm_operations_struct vm_ops = {
.fault = etnaviv_gem_fault,
.open = drm_gem_vm_open,
.close = drm_gem_vm_close,
};
static const struct drm_gem_object_funcs etnaviv_gem_object_funcs = {
.free = etnaviv_gem_free_object,
.pin = etnaviv_gem_prime_pin,
.unpin = etnaviv_gem_prime_unpin,
.get_sg_table = etnaviv_gem_prime_get_sg_table,
.vmap = etnaviv_gem_prime_vmap,
.vunmap = etnaviv_gem_prime_vunmap,
.vm_ops = &vm_ops,
};
static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags,
const struct etnaviv_gem_ops *ops, struct drm_gem_object **obj)
{
@@ -592,6 +608,7 @@ static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags,
INIT_LIST_HEAD(&etnaviv_obj->vram_list);
*obj = &etnaviv_obj->base;
(*obj)->funcs = &etnaviv_gem_object_funcs;
return 0;
}

View File

@@ -99,6 +99,7 @@ struct etnaviv_gem_submit {
int out_fence_id;
struct list_head node; /* GPU active submit list */
struct etnaviv_cmdbuf cmdbuf;
struct pid *pid; /* submitting process */
bool runtime_resumed;
u32 exec_state;
u32 flags;

View File

@@ -93,7 +93,15 @@ static void *etnaviv_gem_prime_vmap_impl(struct etnaviv_gem_object *etnaviv_obj)
static int etnaviv_gem_prime_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
struct vm_area_struct *vma)
{
return dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0);
int ret;
ret = dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0);
if (!ret) {
/* Drop the reference acquired by drm_gem_mmap_obj(). */
drm_gem_object_put(&etnaviv_obj->base);
}
return ret;
}
static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = {

View File

@@ -407,11 +407,14 @@ static void submit_cleanup(struct kref *kref)
dma_fence_put(submit->in_fence);
if (submit->out_fence) {
/* first remove from IDR, so fence can not be found anymore */
mutex_lock(&submit->gpu->fence_lock);
mutex_lock(&submit->gpu->idr_lock);
idr_remove(&submit->gpu->fence_idr, submit->out_fence_id);
mutex_unlock(&submit->gpu->fence_lock);
mutex_unlock(&submit->gpu->idr_lock);
dma_fence_put(submit->out_fence);
}
put_pid(submit->pid);
kfree(submit->pmrs);
kfree(submit);
}
@@ -435,6 +438,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
struct sync_file *sync_file = NULL;
struct ww_acquire_ctx ticket;
int out_fence_fd = -1;
struct pid *pid = get_pid(task_pid(current));
void *stream;
int ret;
@@ -532,6 +536,8 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
goto err_submit_ww_acquire;
}
submit->pid = pid;
ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &submit->cmdbuf,
ALIGN(args->stream_size, 8) + 8);
if (ret)

View File

@@ -13,6 +13,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/string_helpers.h>
#include <linux/thermal.h>
#include "etnaviv_cmdbuf.h"
@@ -27,10 +28,6 @@
#include "state_hi.xml.h"
#include "cmdstream.xml.h"
#ifndef PHYS_OFFSET
#define PHYS_OFFSET 0
#endif
static const struct platform_device_id gpu_ids[] = {
{ .name = "etnaviv-gpu,2d" },
{ },
@@ -156,6 +153,18 @@ int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value)
*value = ~0ULL;
break;
case ETNAVIV_PARAM_GPU_PRODUCT_ID:
*value = gpu->identity.product_id;
break;
case ETNAVIV_PARAM_GPU_CUSTOMER_ID:
*value = gpu->identity.customer_id;
break;
case ETNAVIV_PARAM_GPU_ECO_ID:
*value = gpu->identity.eco_id;
break;
default:
DBG("%s: invalid param: %u", dev_name(gpu->dev), param);
return -EINVAL;
@@ -408,6 +417,12 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
if (gpu->identity.model == chipModel_GC700)
gpu->identity.features &= ~chipFeatures_FAST_CLEAR;
/* These models/revisions don't have the 2D pipe bit */
if ((gpu->identity.model == chipModel_GC500 &&
gpu->identity.revision <= 2) ||
gpu->identity.model == chipModel_GC300)
gpu->identity.features |= chipFeatures_PIPE_2D;
if ((gpu->identity.model == chipModel_GC500 &&
gpu->identity.revision < 2) ||
(gpu->identity.model == chipModel_GC300 &&
@@ -441,8 +456,9 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_5);
}
/* GC600 idle register reports zero bits where modules aren't present */
if (gpu->identity.model == chipModel_GC600)
/* GC600/300 idle register reports zero bits where modules aren't present */
if (gpu->identity.model == chipModel_GC600 ||
gpu->identity.model == chipModel_GC300)
gpu->idle_mask = VIVS_HI_IDLE_STATE_TX |
VIVS_HI_IDLE_STATE_RA |
VIVS_HI_IDLE_STATE_SE |
@@ -478,6 +494,14 @@ static void etnaviv_gpu_update_clock(struct etnaviv_gpu *gpu)
clock |= VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(fscale);
etnaviv_gpu_load_clock(gpu, clock);
}
/*
* Choose number of wait cycles to target a ~30us (1/32768) max latency
* until new work is picked up by the FE when it polls in the idle loop.
* If the GPU base frequency is unknown use 200 wait cycles.
*/
gpu->fe_waitcycles = clamp(gpu->base_rate_core >> (15 - gpu->freq_scale),
200UL, 0xffffUL);
}
static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
@@ -499,7 +523,11 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
control |= VIVS_HI_CLOCK_CONTROL_ISOLATE_GPU;
gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
if (gpu->sec_mode == ETNA_SEC_KERNEL) {
if (etnaviv_is_model_rev(gpu, GC620, 0x5552)) {
gpu_write(gpu, 0x00800, 0x10);
}
if (gpu->identity.minor_features7 & chipMinorFeatures7_BIT_SECURITY) {
gpu_write(gpu, VIVS_MMUv2_AHB_CONTROL,
VIVS_MMUv2_AHB_CONTROL_RESET);
} else {
@@ -561,7 +589,7 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
/* We rely on the GPU running, so program the clock */
etnaviv_gpu_update_clock(gpu);
gpu->fe_running = false;
gpu->state = ETNA_GPU_STATE_RESET;
gpu->exec_state = -1;
if (gpu->mmu_context)
etnaviv_iommu_context_put(gpu->mmu_context);
@@ -629,8 +657,6 @@ void etnaviv_gpu_start_fe(struct etnaviv_gpu *gpu, u32 address, u16 prefetch)
VIVS_MMUv2_SEC_COMMAND_CONTROL_ENABLE |
VIVS_MMUv2_SEC_COMMAND_CONTROL_PREFETCH(prefetch));
}
gpu->fe_running = true;
}
static void etnaviv_gpu_start_fe_idleloop(struct etnaviv_gpu *gpu,
@@ -639,6 +665,8 @@ static void etnaviv_gpu_start_fe_idleloop(struct etnaviv_gpu *gpu,
u16 prefetch;
u32 address;
WARN_ON(gpu->state != ETNA_GPU_STATE_INITIALIZED);
/* setup the MMU */
etnaviv_iommu_restore(gpu, context);
@@ -648,6 +676,8 @@ static void etnaviv_gpu_start_fe_idleloop(struct etnaviv_gpu *gpu,
&gpu->mmu_context->cmdbuf_mapping);
etnaviv_gpu_start_fe(gpu, address, prefetch);
gpu->state = ETNA_GPU_STATE_RUNNING;
}
static void etnaviv_gpu_setup_pulse_eater(struct etnaviv_gpu *gpu)
@@ -683,6 +713,9 @@ static void etnaviv_gpu_setup_pulse_eater(struct etnaviv_gpu *gpu)
static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
{
WARN_ON(!(gpu->state == ETNA_GPU_STATE_IDENTIFIED ||
gpu->state == ETNA_GPU_STATE_RESET));
if ((etnaviv_is_model_rev(gpu, GC320, 0x5007) ||
etnaviv_is_model_rev(gpu, GC320, 0x5220)) &&
gpu_read(gpu, VIVS_HI_CHIP_TIME) != 0x2062400) {
@@ -719,7 +752,13 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
gpu_write(gpu, VIVS_MC_BUS_CONFIG, bus_config);
}
if (gpu->sec_mode == ETNA_SEC_KERNEL) {
/* FIXME: use feature bit 5 of minor features 12, G2D_DEC400EX */
if (etnaviv_is_model_rev(gpu, GC620, 0x5552)) {
gpu_write(gpu, 0x800, 0x2010188);
gpu_write(gpu, 0x808, 0x3fc104);
}
if (gpu->identity.minor_features7 & chipMinorFeatures7_BIT_SECURITY) {
u32 val = gpu_read(gpu, VIVS_MMUv2_AHB_CONTROL);
val |= VIVS_MMUv2_AHB_CONTROL_NONSEC_ACCESS;
gpu_write(gpu, VIVS_MMUv2_AHB_CONTROL, val);
@@ -729,11 +768,14 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
etnaviv_gpu_setup_pulse_eater(gpu);
gpu_write(gpu, VIVS_HI_INTR_ENBL, ~0U);
gpu->state = ETNA_GPU_STATE_INITIALIZED;
}
int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
{
struct etnaviv_drm_private *priv = gpu->drm->dev_private;
dma_addr_t cmdbuf_paddr;
int ret, i;
ret = pm_runtime_get_sync(gpu->dev);
@@ -762,10 +804,12 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
* On cores with security features supported, we claim control over the
* security states.
*/
if ((gpu->identity.minor_features7 & chipMinorFeatures7_BIT_SECURITY) &&
if ((gpu->identity.minor_features7 & chipMinorFeatures7_BIT_SECURITY) ||
(gpu->identity.minor_features10 & chipMinorFeatures10_SECURITY_AHB))
gpu->sec_mode = ETNA_SEC_KERNEL;
gpu->state = ETNA_GPU_STATE_IDENTIFIED;
ret = etnaviv_hw_reset(gpu);
if (ret) {
dev_err(gpu->dev, "GPU reset failed\n");
@@ -776,28 +820,6 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
if (ret)
goto fail;
/*
* Set the GPU linear window to be at the end of the DMA window, where
* the CMA area is likely to reside. This ensures that we are able to
* map the command buffers while having the linear window overlap as
* much RAM as possible, so we can optimize mappings for other buffers.
*
* For 3D cores only do this if MC2.0 is present, as with MC1.0 it leads
* to different views of the memory on the individual engines.
*/
if (!(gpu->identity.features & chipFeatures_PIPE_3D) ||
(gpu->identity.minor_features0 & chipMinorFeatures0_MC20)) {
u32 dma_mask = (u32)dma_get_required_mask(gpu->dev);
if (dma_mask < PHYS_OFFSET + SZ_2G)
priv->mmu_global->memory_base = PHYS_OFFSET;
else
priv->mmu_global->memory_base = dma_mask - SZ_2G + 1;
} else if (PHYS_OFFSET >= SZ_2G) {
dev_info(gpu->dev, "Need to move linear window on MC1.0, disabling TS\n");
priv->mmu_global->memory_base = PHYS_OFFSET;
gpu->identity.features &= ~chipFeatures_FAST_CLEAR;
}
/*
* If the GPU is part of a system with DMA addressing limitations,
* request pages for our SHM backend buffers from the DMA32 zone to
@@ -814,6 +836,31 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
goto fail;
}
/*
* Set the GPU linear window to cover the cmdbuf region, as the GPU
* won't be able to start execution otherwise. The alignment to 128M is
* chosen arbitrarily but helps in debugging, as the MMU offset
* calculations are much more straight forward this way.
*
* On MC1.0 cores the linear window offset is ignored by the TS engine,
* leading to inconsistent memory views. Avoid using the offset on those
* cores if possible, otherwise disable the TS feature.
*/
cmdbuf_paddr = ALIGN_DOWN(etnaviv_cmdbuf_get_pa(&gpu->buffer), SZ_128M);
if (!(gpu->identity.features & chipFeatures_PIPE_3D) ||
(gpu->identity.minor_features0 & chipMinorFeatures0_MC20)) {
if (cmdbuf_paddr >= SZ_2G)
priv->mmu_global->memory_base = SZ_2G;
else
priv->mmu_global->memory_base = cmdbuf_paddr;
} else if (cmdbuf_paddr + SZ_128M >= SZ_2G) {
dev_info(gpu->dev,
"Need to move linear window on MC1.0, disabling TS\n");
gpu->identity.features &= ~chipFeatures_FAST_CLEAR;
priv->mmu_global->memory_base = SZ_2G;
}
/* Setup event management */
spin_lock_init(&gpu->event_spinlock);
init_completion(&gpu->event_free);
@@ -829,8 +876,6 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
pm_runtime_mark_last_busy(gpu->dev);
pm_runtime_put_autosuspend(gpu->dev);
gpu->initialized = true;
return 0;
fail:
@@ -1027,12 +1072,28 @@ pm_put:
}
#endif
void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu)
void etnaviv_gpu_recover_hang(struct etnaviv_gem_submit *submit)
{
struct etnaviv_gpu *gpu = submit->gpu;
char *comm = NULL, *cmd = NULL;
struct task_struct *task;
unsigned int i = 0;
dev_err(gpu->dev, "recover hung GPU!\n");
task = get_pid_task(submit->pid, PIDTYPE_PID);
if (task) {
comm = kstrdup(task->comm, GFP_KERNEL);
cmd = kstrdup_quotable_cmdline(task, GFP_KERNEL);
put_task_struct(task);
}
if (comm && cmd)
dev_err(gpu->dev, "offending task: %s (%s)\n", comm, cmd);
kfree(cmd);
kfree(comm);
if (pm_runtime_get_sync(gpu->dev) < 0)
goto pm_put;
@@ -1359,7 +1420,7 @@ struct dma_fence *etnaviv_gpu_submit(struct etnaviv_gem_submit *submit)
goto out_unlock;
}
if (!gpu->fe_running)
if (gpu->state == ETNA_GPU_STATE_INITIALIZED)
etnaviv_gpu_start_fe_idleloop(gpu, submit->mmu_context);
if (submit->prev_mmu_context)
@@ -1408,6 +1469,15 @@ static void sync_point_worker(struct work_struct *work)
static void dump_mmu_fault(struct etnaviv_gpu *gpu)
{
static const char *fault_reasons[] = {
"slave not present",
"page not present",
"write violation",
"out of bounds",
"read security violation",
"write security violation",
};
u32 status_reg, status;
int i;
@@ -1420,18 +1490,25 @@ static void dump_mmu_fault(struct etnaviv_gpu *gpu)
dev_err_ratelimited(gpu->dev, "MMU fault status 0x%08x\n", status);
for (i = 0; i < 4; i++) {
const char *reason = "unknown";
u32 address_reg;
u32 mmu_status;
if (!(status & (VIVS_MMUv2_STATUS_EXCEPTION0__MASK << (i * 4))))
mmu_status = (status >> (i * 4)) & VIVS_MMUv2_STATUS_EXCEPTION0__MASK;
if (!mmu_status)
continue;
if ((mmu_status - 1) < ARRAY_SIZE(fault_reasons))
reason = fault_reasons[mmu_status - 1];
if (gpu->sec_mode == ETNA_SEC_NONE)
address_reg = VIVS_MMUv2_EXCEPTION_ADDR(i);
else
address_reg = VIVS_MMUv2_SEC_EXCEPTION_ADDR;
dev_err_ratelimited(gpu->dev, "MMU %d fault addr 0x%08x\n", i,
gpu_read(gpu, address_reg));
dev_err_ratelimited(gpu->dev,
"MMU %d fault (%s) addr 0x%08x\n",
i, reason, gpu_read(gpu, address_reg));
}
}
@@ -1456,6 +1533,8 @@ static irqreturn_t irq_handler(int irq, void *data)
if (intr & VIVS_HI_INTR_ACKNOWLEDGE_MMU_EXCEPTION) {
dump_mmu_fault(gpu);
gpu->state = ETNA_GPU_STATE_FAULT;
drm_sched_fault(&gpu->sched);
intr &= ~VIVS_HI_INTR_ACKNOWLEDGE_MMU_EXCEPTION;
}
@@ -1566,7 +1645,7 @@ int etnaviv_gpu_wait_idle(struct etnaviv_gpu *gpu, unsigned int timeout_ms)
static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu)
{
if (gpu->initialized && gpu->fe_running) {
if (gpu->state == ETNA_GPU_STATE_RUNNING) {
/* Replace the last WAIT with END */
mutex_lock(&gpu->lock);
etnaviv_buffer_end(gpu);
@@ -1579,11 +1658,13 @@ static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu)
*/
etnaviv_gpu_wait_idle(gpu, 100);
gpu->fe_running = false;
gpu->state = ETNA_GPU_STATE_INITIALIZED;
}
gpu->exec_state = -1;
gpu->state = ETNA_GPU_STATE_IDENTIFIED;
return etnaviv_gpu_clk_disable(gpu);
}
@@ -1671,13 +1752,11 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master,
if (ret)
goto out_workqueue;
#ifdef CONFIG_PM
ret = pm_runtime_get_sync(gpu->dev);
#else
#ifndef CONFIG_PM
ret = etnaviv_gpu_clk_enable(gpu);
#endif
if (ret < 0)
goto out_sched;
#endif
gpu->drm = drm;
@@ -1690,9 +1769,6 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master,
priv->gpu[priv->num_gpus++] = gpu;
pm_runtime_mark_last_busy(gpu->dev);
pm_runtime_put_autosuspend(gpu->dev);
return 0;
out_sched:
@@ -1730,11 +1806,8 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master,
if (gpu->mmu_context)
etnaviv_iommu_context_put(gpu->mmu_context);
if (gpu->initialized) {
etnaviv_cmdbuf_free(&gpu->buffer);
etnaviv_iommu_global_fini(gpu);
gpu->initialized = false;
}
etnaviv_cmdbuf_free(&gpu->buffer);
etnaviv_iommu_global_fini(gpu);
gpu->drm = NULL;
idr_destroy(&gpu->fence_idr);
@@ -1769,7 +1842,8 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
gpu->dev = &pdev->dev;
mutex_init(&gpu->lock);
mutex_init(&gpu->fence_lock);
mutex_init(&gpu->sched_lock);
mutex_init(&gpu->idr_lock);
/* Map registers: */
gpu->mmio = devm_platform_ioremap_resource(pdev, 0);
@@ -1874,7 +1948,7 @@ static int etnaviv_gpu_rpm_resume(struct device *dev)
return ret;
/* Re-initialise the basic hardware state */
if (gpu->drm && gpu->initialized) {
if (gpu->state == ETNA_GPU_STATE_IDENTIFIED) {
ret = etnaviv_gpu_hw_resume(gpu);
if (ret) {
etnaviv_gpu_clk_disable(gpu);

View File

@@ -91,6 +91,15 @@ struct clk;
#define ETNA_NR_EVENTS 30
enum etnaviv_gpu_state {
ETNA_GPU_STATE_UNKNOWN = 0,
ETNA_GPU_STATE_IDENTIFIED,
ETNA_GPU_STATE_RESET,
ETNA_GPU_STATE_INITIALIZED,
ETNA_GPU_STATE_RUNNING,
ETNA_GPU_STATE_FAULT,
};
struct etnaviv_gpu {
struct drm_device *drm;
struct thermal_cooling_device *cooling;
@@ -99,9 +108,9 @@ struct etnaviv_gpu {
struct etnaviv_chip_identity identity;
enum etnaviv_sec_mode sec_mode;
struct workqueue_struct *wq;
struct mutex sched_lock;
struct drm_gpu_scheduler sched;
bool initialized;
bool fe_running;
enum etnaviv_gpu_state state;
/* 'ring'-buffer: */
struct etnaviv_cmdbuf buffer;
@@ -116,7 +125,7 @@ struct etnaviv_gpu {
u32 idle_mask;
/* Fencing support */
struct mutex fence_lock;
struct mutex idr_lock;
struct idr fence_idr;
u32 next_fence;
u32 completed_fence;
@@ -145,6 +154,7 @@ struct etnaviv_gpu {
struct clk *clk_shader;
unsigned int freq_scale;
unsigned int fe_waitcycles;
unsigned long base_rate_core;
unsigned long base_rate_shader;
};
@@ -168,7 +178,7 @@ bool etnaviv_fill_identity_from_hwdb(struct etnaviv_gpu *gpu);
int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m);
#endif
void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu);
void etnaviv_gpu_recover_hang(struct etnaviv_gem_submit *submit);
void etnaviv_gpu_retire(struct etnaviv_gpu *gpu);
int etnaviv_gpu_wait_fence_interruptible(struct etnaviv_gpu *gpu,
u32 fence, struct drm_etnaviv_timespec *timeout);

View File

@@ -37,6 +37,37 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
.minor_features10 = 0x0,
.minor_features11 = 0x0,
},
{
.model = 0x620,
.revision = 0x5552,
.product_id = 0x6200,
.customer_id = 0x20b,
.eco_id = 0,
.stream_count = 1,
.register_max = 64,
.thread_count = 256,
.shader_core_count = 1,
.vertex_cache_size = 8,
.vertex_output_buffer_size = 512,
.pixel_pipes = 1,
.instruction_count = 256,
.num_constants = 168,
.buffer_size = 0,
.varyings_count = 8,
.features = 0x001b4a40,
.minor_features0 = 0xa0600080,
.minor_features1 = 0x18050000,
.minor_features2 = 0x04f30000,
.minor_features3 = 0x00060005,
.minor_features4 = 0x20629000,
.minor_features5 = 0x0003380c,
.minor_features6 = 0x00000000,
.minor_features7 = 0x00001000,
.minor_features8 = 0x00000000,
.minor_features9 = 0x00000180,
.minor_features10 = 0x00004000,
.minor_features11 = 0x00000000,
},
{
.model = 0x7000,
.revision = 0x6214,

View File

@@ -186,6 +186,14 @@ static void etnaviv_iommuv2_restore_nonsec(struct etnaviv_gpu *gpu,
gpu_write(gpu, VIVS_MMUv2_CONTROL, VIVS_MMUv2_CONTROL_ENABLE);
}
void etnaviv_iommuv2_update_pta_entry(struct etnaviv_iommu_context *context)
{
struct etnaviv_iommuv2_context *v2_context = to_v2_context(context);
context->global->v2.pta_cpu[v2_context->id] = v2_context->mtlb_dma |
VIVS_MMUv2_CONFIGURATION_MODE_MODE4_K;
}
static void etnaviv_iommuv2_restore_sec(struct etnaviv_gpu *gpu,
struct etnaviv_iommu_context *context)
{
@@ -216,8 +224,7 @@ static void etnaviv_iommuv2_restore_sec(struct etnaviv_gpu *gpu,
VIVS_MMUv2_SAFE_ADDRESS_CONFIG_SEC_SAFE_ADDR_HIGH(
upper_32_bits(context->global->bad_page_dma)));
context->global->v2.pta_cpu[v2_context->id] = v2_context->mtlb_dma |
VIVS_MMUv2_CONFIGURATION_MODE_MODE4_K;
etnaviv_iommuv2_update_pta_entry(context);
/* trigger a PTA load through the FE */
prefetch = etnaviv_buffer_config_pta(gpu, v2_context->id);
@@ -241,6 +248,7 @@ unsigned short etnaviv_iommuv2_get_pta_id(struct etnaviv_iommu_context *context)
return v2_context->id;
}
static void etnaviv_iommuv2_restore(struct etnaviv_gpu *gpu,
struct etnaviv_iommu_context *context)
{
@@ -276,6 +284,8 @@ etnaviv_iommuv2_context_alloc(struct etnaviv_iommu_global *global)
if (!v2_context)
return NULL;
v2_context->id = 0;
#if 0
mutex_lock(&global->lock);
v2_context->id = find_first_zero_bit(global->v2.pta_alloc,
ETNAVIV_PTA_ENTRIES);
@@ -286,6 +296,7 @@ etnaviv_iommuv2_context_alloc(struct etnaviv_iommu_global *global)
goto out_free;
}
mutex_unlock(&global->lock);
#endif
v2_context->mtlb_cpu = dma_alloc_wc(global->dev, SZ_4K,
&v2_context->mtlb_dma, GFP_KERNEL);

View File

@@ -80,10 +80,10 @@ static int etnaviv_iommu_map(struct etnaviv_iommu_context *context, u32 iova,
return -EINVAL;
for_each_sgtable_dma_sg(sgt, sg, i) {
u32 pa = sg_dma_address(sg) - sg->offset;
phys_addr_t pa = sg_dma_address(sg) - sg->offset;
size_t bytes = sg_dma_len(sg) + sg->offset;
VERB("map[%d]: %08x %08x(%zx)", i, iova, pa, bytes);
VERB("map[%d]: %08x %pap(%zx)", i, iova, &pa, bytes);
ret = etnaviv_context_map(context, da, pa, bytes, prot);
if (ret)
@@ -92,6 +92,8 @@ static int etnaviv_iommu_map(struct etnaviv_iommu_context *context, u32 iova,
da += bytes;
}
context->flush_seq++;
return 0;
fail:
@@ -117,6 +119,8 @@ static void etnaviv_iommu_unmap(struct etnaviv_iommu_context *context, u32 iova,
da += bytes;
}
context->flush_seq++;
}
static void etnaviv_iommu_remove_mapping(struct etnaviv_iommu_context *context,
@@ -124,11 +128,26 @@ static void etnaviv_iommu_remove_mapping(struct etnaviv_iommu_context *context,
{
struct etnaviv_gem_object *etnaviv_obj = mapping->object;
lockdep_assert_held(&context->lock);
etnaviv_iommu_unmap(context, mapping->vram_node.start,
etnaviv_obj->sgt, etnaviv_obj->base.size);
drm_mm_remove_node(&mapping->vram_node);
}
void etnaviv_iommu_reap_mapping(struct etnaviv_vram_mapping *mapping)
{
struct etnaviv_iommu_context *context = mapping->context;
lockdep_assert_held(&context->lock);
WARN_ON(mapping->use);
etnaviv_iommu_remove_mapping(context, mapping);
etnaviv_iommu_context_put(mapping->context);
mapping->context = NULL;
list_del_init(&mapping->mmu_node);
}
static int etnaviv_iommu_find_iova(struct etnaviv_iommu_context *context,
struct drm_mm_node *node, size_t size)
{
@@ -196,10 +215,7 @@ static int etnaviv_iommu_find_iova(struct etnaviv_iommu_context *context,
* this mapping.
*/
list_for_each_entry_safe(m, n, &list, scan_node) {
etnaviv_iommu_remove_mapping(context, m);
etnaviv_iommu_context_put(m->context);
m->context = NULL;
list_del_init(&m->mmu_node);
etnaviv_iommu_reap_mapping(m);
list_del_init(&m->scan_node);
}
@@ -217,6 +233,44 @@ static int etnaviv_iommu_find_iova(struct etnaviv_iommu_context *context,
static int etnaviv_iommu_insert_exact(struct etnaviv_iommu_context *context,
struct drm_mm_node *node, size_t size, u64 va)
{
struct etnaviv_vram_mapping *m, *n;
struct drm_mm_node *scan_node;
LIST_HEAD(scan_list);
int ret;
lockdep_assert_held(&context->lock);
ret = drm_mm_insert_node_in_range(&context->mm, node, size, 0, 0, va,
va + size, DRM_MM_INSERT_LOWEST);
if (ret != -ENOSPC)
return ret;
/*
* When we can't insert the node, due to a existing mapping blocking
* the address space, there are two possible reasons:
* 1. Userspace genuinely messed up and tried to reuse address space
* before the last job using this VMA has finished executing.
* 2. The existing buffer mappings are idle, but the buffers are not
* destroyed yet (likely due to being referenced by another context) in
* which case the mappings will not be cleaned up and we must reap them
* here to make space for the new mapping.
*/
drm_mm_for_each_node_in_range(scan_node, &context->mm, va, va + size) {
m = container_of(scan_node, struct etnaviv_vram_mapping,
vram_node);
if (m->use)
return -ENOSPC;
list_add(&m->scan_node, &scan_list);
}
list_for_each_entry_safe(m, n, &scan_list, scan_node) {
etnaviv_iommu_reap_mapping(m);
list_del_init(&m->scan_node);
}
return drm_mm_insert_node_in_range(&context->mm, node, size, 0, 0, va,
va + size, DRM_MM_INSERT_LOWEST);
}
@@ -241,6 +295,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu_context *context,
iova = sg_dma_address(sgt->sgl) - memory_base;
if (iova < 0x80000000 - sg_dma_len(sgt->sgl)) {
mapping->iova = iova;
mapping->context = etnaviv_iommu_context_get(context);
list_add_tail(&mapping->mmu_node, &context->mappings);
ret = 0;
goto unlock;
@@ -267,8 +322,8 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu_context *context,
goto unlock;
}
mapping->context = etnaviv_iommu_context_get(context);
list_add_tail(&mapping->mmu_node, &context->mappings);
context->flush_seq++;
unlock:
mutex_unlock(&context->lock);
@@ -282,13 +337,19 @@ void etnaviv_iommu_unmap_gem(struct etnaviv_iommu_context *context,
mutex_lock(&context->lock);
/* Bail if the mapping has been reaped by another thread */
if (!mapping->context) {
mutex_unlock(&context->lock);
return;
}
/* If the vram node is on the mm, unmap and remove the node */
if (mapping->vram_node.mm == &context->mm)
etnaviv_iommu_remove_mapping(context, mapping);
list_del(&mapping->mmu_node);
context->flush_seq++;
mutex_unlock(&context->lock);
etnaviv_iommu_context_put(context);
}
static void etnaviv_iommu_context_free(struct kref *kref)
@@ -492,6 +553,9 @@ void etnaviv_iommu_global_fini(struct etnaviv_gpu *gpu)
struct etnaviv_drm_private *priv = gpu->drm->dev_private;
struct etnaviv_iommu_global *global = priv->mmu_global;
if (!global)
return;
if (--global->use > 0)
return;

View File

@@ -91,6 +91,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu_context *context,
struct etnaviv_vram_mapping *mapping, u64 va);
void etnaviv_iommu_unmap_gem(struct etnaviv_iommu_context *context,
struct etnaviv_vram_mapping *mapping);
void etnaviv_iommu_reap_mapping(struct etnaviv_vram_mapping *mapping);
int etnaviv_iommu_get_suballoc_va(struct etnaviv_iommu_context *ctx,
struct etnaviv_vram_mapping *mapping,
@@ -123,4 +124,6 @@ etnaviv_iommuv2_context_alloc(struct etnaviv_iommu_global *global);
u32 etnaviv_iommuv2_get_mtlb_addr(struct etnaviv_iommu_context *context);
unsigned short etnaviv_iommuv2_get_pta_id(struct etnaviv_iommu_context *context);
void etnaviv_iommuv2_update_pta_entry(struct etnaviv_iommu_context *context);
#endif /* __ETNAVIV_MMU_H__ */

View File

@@ -106,8 +106,9 @@ static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job)
*/
dma_addr = gpu_read(gpu, VIVS_FE_DMA_ADDRESS);
change = dma_addr - gpu->hangcheck_dma_addr;
if (gpu->completed_fence != gpu->hangcheck_fence ||
change < 0 || change > 16) {
if (gpu->state == ETNA_GPU_STATE_RUNNING &&
(gpu->completed_fence != gpu->hangcheck_fence ||
change < 0 || change > 16)) {
gpu->hangcheck_dma_addr = dma_addr;
gpu->hangcheck_fence = gpu->completed_fence;
goto out_no_timeout;
@@ -118,7 +119,7 @@ static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job)
/* get the GPU back into the init state */
etnaviv_core_dump(submit);
etnaviv_gpu_recover_hang(gpu);
etnaviv_gpu_recover_hang(submit);
drm_sched_resubmit_jobs(&gpu->sched);
@@ -146,14 +147,16 @@ static const struct drm_sched_backend_ops etnaviv_sched_ops = {
int etnaviv_sched_push_job(struct drm_sched_entity *sched_entity,
struct etnaviv_gem_submit *submit)
{
struct etnaviv_gpu *gpu = submit->gpu;
int ret = 0;
/*
* Hold the fence lock across the whole operation to avoid jobs being
* Hold the sched lock across the whole operation to avoid jobs being
* pushed out of order with regard to their sched fence seqnos as
* allocated in drm_sched_job_init.
*/
mutex_lock(&submit->gpu->fence_lock);
mutex_lock(&gpu->sched_lock);
ret = drm_sched_job_init(&submit->sched_job, sched_entity,
submit->ctx);
@@ -161,9 +164,11 @@ int etnaviv_sched_push_job(struct drm_sched_entity *sched_entity,
goto out_unlock;
submit->out_fence = dma_fence_get(&submit->sched_job.s_fence->finished);
submit->out_fence_id = idr_alloc_cyclic(&submit->gpu->fence_idr,
mutex_lock(&gpu->idr_lock);
submit->out_fence_id = idr_alloc_cyclic(&gpu->fence_idr,
submit->out_fence, 0,
INT_MAX, GFP_KERNEL);
mutex_unlock(&gpu->idr_lock);
if (submit->out_fence_id < 0) {
drm_sched_job_cleanup(&submit->sched_job);
ret = -ENOMEM;
@@ -176,7 +181,7 @@ int etnaviv_sched_push_job(struct drm_sched_entity *sched_entity,
drm_sched_entity_push_job(&submit->sched_job, sched_entity);
out_unlock:
mutex_unlock(&submit->gpu->fence_lock);
mutex_unlock(&gpu->sched_lock);
return ret;
}

View File

@@ -1,4 +1,4 @@
img_basedir := drivers/gpu/drm/img-rogue
img_basedir := $(srctree)/$(src)
include $(img_basedir)/config_kernel.mk
obj-$(CONFIG_DRM_POWERVR_ROGUE) += pvrsrvkm.o

View File

@@ -519,4 +519,13 @@ config DRM_PANEL_HX8394
Say Y if you want to enable support for panels based on the
HX8394 controller.
config DRM_PANEL_JADARD_JD9365DA_H3
tristate "Jadard JD9365DA-H3 WXGA DSI panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
Say Y here if you want to enable support for Jadard JD9365DA-H3
WXGA MIPI DSI panel. The panel support TFT dot matrix LCD with
800RGBx1280 dots at maximum.
endmenu

View File

@@ -55,3 +55,4 @@ obj-$(CONFIG_DRM_PANEL_VISIONOX_RM69299) += panel-visionox-rm69299.o
obj-$(CONFIG_DRM_PANEL_XINPENG_XPP055C272) += panel-xinpeng-xpp055c272.o
obj-$(CONFIG_DRM_PANEL_ILI9881D) += panel-ili9881d.o
obj-$(CONFIG_DRM_PANEL_HX8394) += panel-himax8394.o
obj-$(CONFIG_DRM_PANEL_JADARD_JD9365DA_H3) += panel-jadard-jd9365da-h3.o

View File

@@ -0,0 +1,356 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2019 Radxa Limited
* Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
*
* Author:
* - Jagan Teki <jagan@amarulasolutions.com>
* - Stephen Chen <stephen@radxa.com>
*/
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/gpio/consumer.h>
#include <linux/regulator/consumer.h>
#include <drm/drm_device.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_modes.h>
#include <drm/drm_panel.h>
#include <video/mipi_display.h>
struct jadard_panel_desc {
const struct drm_display_mode *display_mode;
unsigned long mode_flags;
enum mipi_dsi_pixel_format format;
unsigned int lanes;
// const struct jadard_panel_cmd *on_cmds;
unsigned int on_cmds_num;
};
struct panel_info {
struct drm_panel base;
struct mipi_dsi_device *link;
const struct jadard_panel_desc *desc;
struct gpio_desc *reset;
struct regulator *hsvcc;
struct regulator *vspn3v3;
bool prepared;
bool enabled;
};
static inline struct panel_info *to_panel_info(struct drm_panel *panel)
{
return container_of(panel, struct panel_info, base);
}
//static int jadard_send_mipi_cmds(struct drm_panel *panel, const struct jadard_panel_cmd *cmds)
//{
// struct panel_info *pinfo = to_panel_info(panel);
// unsigned int i = 0;
// int err;
//
// for (i = 0; i < pinfo->desc->on_cmds_num; i++) {
// err = mipi_dsi_dcs_write_buffer(pinfo->link, &(cmds[i].cmddata[0]), cmds[i].cmdlen);
// if (err < 0)
// return err;
// }
//
// return 0;
//}
static int jadard_disable(struct drm_panel *panel)
{
struct panel_info *pinfo = to_panel_info(panel);
int err;
if (!pinfo->enabled)
return 0;
err = mipi_dsi_dcs_set_display_off(pinfo->link);
if (err < 0) {
dev_err(panel->dev, "failed to set display off: %d\n", err);
return err;
}
pinfo->enabled = false;
return 0;
}
static int jadard_unprepare(struct drm_panel *panel)
{
struct panel_info *pinfo = to_panel_info(panel);
int err;
if (!pinfo->prepared)
return 0;
err = mipi_dsi_dcs_set_display_off(pinfo->link);
if (err < 0)
dev_err(panel->dev, "failed to set display off: %d\n", err);
err = mipi_dsi_dcs_enter_sleep_mode(pinfo->link);
if (err < 0)
dev_err(panel->dev, "failed to enter sleep mode: %d\n", err);
/* sleep_mode_delay: 1ms - 2ms */
usleep_range(1000, 2000);
gpiod_set_value(pinfo->reset, 1);
regulator_disable(pinfo->hsvcc);
regulator_disable(pinfo->vspn3v3);
pinfo->prepared = false;
return 0;
}
static int jadard_prepare(struct drm_panel *panel)
{
struct panel_info *pinfo = to_panel_info(panel);
int ret;
if (pinfo->prepared)
return 0;
gpiod_set_value(pinfo->reset, 0);
/* Power the panel */
ret = regulator_enable(pinfo->hsvcc);
if (ret) {
dev_err(pinfo->base.dev, "Failed to enable hsvcc supply: %d\n", ret);
return ret;
}
usleep_range(1000, 2000);
ret = regulator_enable(pinfo->vspn3v3);
if (ret) {
dev_err(pinfo->base.dev, "Failed to enable vspn3v3 supply: %d\n", ret);
goto fail;
}
usleep_range(5000, 6000);
gpiod_set_value(pinfo->reset, 1);
msleep(180);
pinfo->prepared = true;
return 0;
fail:
gpiod_set_value(pinfo->reset, 1);
regulator_disable(pinfo->hsvcc);
return ret;
}
static int jadard_enable(struct drm_panel *panel)
{
struct panel_info *pinfo = to_panel_info(panel);
int ret;
if (pinfo->enabled)
return 0;
ret = mipi_dsi_dcs_exit_sleep_mode(pinfo->link);
if (ret < 0) {
dev_err(panel->dev, "failed to exit sleep mode: %d\n", ret);
return ret;
}
msleep(120);
ret = mipi_dsi_dcs_set_display_on(pinfo->link);
if (ret < 0) {
dev_err(panel->dev, "failed to set display on: %d\n", ret);
return ret;
}
pinfo->enabled = true;
return 0;
}
static int jadard_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
{
struct panel_info *pinfo = to_panel_info(panel);
const struct drm_display_mode *m = pinfo->desc->display_mode;
struct drm_display_mode *mode;
mode = drm_mode_duplicate(connector->dev, m);
if (!mode) {
dev_err(pinfo->base.dev, "failed to add mode %ux%u@%u\n",
m->hdisplay, m->vdisplay, drm_mode_vrefresh(m));
return -ENOMEM;
}
drm_mode_set_name(mode);
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, mode);
connector->display_info.width_mm = mode->width_mm;
connector->display_info.height_mm = mode->height_mm;
return 1;
}
static const struct drm_panel_funcs panel_funcs = {
.disable = jadard_disable,
.unprepare = jadard_unprepare,
.prepare = jadard_prepare,
.enable = jadard_enable,
.get_modes = jadard_get_modes,
};
static const struct drm_display_mode jadard_default_mode = {
.clock = 76000,
.hdisplay = 800,
.hsync_start = 800 + 32,
.hsync_end = 800 + 32 + 8,
.htotal = 800 + 32 + 8 + 32,
.vdisplay = 1280,
.vsync_start = 1280 + 16,
.vsync_end = 1280 + 16 + 8,
.vtotal = 1280 + 16 + 8 + 16,
.width_mm = 62,
.height_mm = 110,
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
};
static const struct jadard_panel_desc jadard_panel_desc = {
.display_mode = &jadard_default_mode,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_VIDEO_BURST,
.format = MIPI_DSI_FMT_RGB888,
.lanes = 4,
};
static const struct of_device_id panel_of_match[] = {
{
.compatible = "jadard,jd9365da-h3",
.data = &jadard_panel_desc,
},
{
/* sentinel */
}
};
MODULE_DEVICE_TABLE(of, panel_of_match);
static int jd9365da_panel_add(struct panel_info *pinfo)
{
struct device *dev = &pinfo->link->dev;
int ret;
pinfo->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(pinfo->reset))
return dev_err_probe(dev, PTR_ERR(pinfo->reset),
"Couldn't get our reset GPIO\n");
pinfo->hsvcc = devm_regulator_get(dev, "hsvcc");
if (IS_ERR(pinfo->hsvcc))
return dev_err_probe(dev, PTR_ERR(pinfo->hsvcc),
"Failed to request hsvcc regulator\n");
pinfo->vspn3v3 = devm_regulator_get(dev, "vspn3v3");
if (IS_ERR(pinfo->vspn3v3))
return dev_err_probe(dev, PTR_ERR(pinfo->vspn3v3),
"Failed to request vspn3v3 regulator\n");
drm_panel_init(&pinfo->base, dev, &panel_funcs,
DRM_MODE_CONNECTOR_DSI);
ret = drm_panel_of_backlight(&pinfo->base);
if (ret)
return ret;
drm_panel_add(&pinfo->base);
return 0;
}
static int jadard_dsi_probe(struct mipi_dsi_device *dsi)
{
struct panel_info *pinfo;
const struct jadard_panel_desc *desc;
int err;
pinfo = devm_kzalloc(&dsi->dev, sizeof(*pinfo), GFP_KERNEL);
if (!pinfo)
return -ENOMEM;
desc = of_device_get_match_data(&dsi->dev);
dsi->mode_flags = desc->mode_flags;
dsi->format = desc->format;
dsi->lanes = desc->lanes;
pinfo->desc = desc;
pinfo->link = dsi;
mipi_dsi_set_drvdata(dsi, pinfo);
err = jd9365da_panel_add(pinfo);
if (err < 0)
return err;
err = mipi_dsi_attach(dsi);
if (err < 0)
drm_panel_remove(&pinfo->base);
return err;
}
static int jadard_dsi_remove(struct mipi_dsi_device *dsi)
{
struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
int err;
err = jadard_disable(&pinfo->base);
if (err < 0)
dev_err(&dsi->dev, "failed to disable panel: %d\n", err);
err = jadard_unprepare(&pinfo->base);
if (err < 0)
dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err);
err = mipi_dsi_detach(dsi);
if (err < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
drm_panel_remove(&pinfo->base);
return 0;
}
static void jd9365da_panel_shutdown(struct mipi_dsi_device *dsi)
{
struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
jadard_disable(&pinfo->base);
jadard_unprepare(&pinfo->base);
}
static struct mipi_dsi_driver jadard_driver = {
.driver = {
.name = "jadard-jd9365da",
.of_match_table = panel_of_match,
},
.probe = jadard_dsi_probe,
.remove = jadard_dsi_remove,
.shutdown = jd9365da_panel_shutdown,
};
module_mipi_dsi_driver(jadard_driver);
MODULE_AUTHOR("Jagan Teki <jagan@edgeble.ai>");
MODULE_AUTHOR("Stephen Chen <stephen@radxa.com>");
MODULE_DESCRIPTION("Jadard JD9365DA-H3 WXGA DSI panel");
MODULE_LICENSE("GPL");

View File

@@ -745,8 +745,8 @@ static void update_cursor_plane(struct vs_dc *dc, struct vs_plane *plane)
struct dc_hw_cursor cursor;
cursor.address = plane->dma_addr[0];
cursor.x = state->crtc_x;
cursor.y = state->crtc_y;
cursor.x = state->crtc_x + drm_fb->hot_x;
cursor.y = state->crtc_y + drm_fb->hot_y;
cursor.hot_x = drm_fb->hot_x;
cursor.hot_y = drm_fb->hot_y;
cursor.display_id = to_vs_display_id(dc, state->crtc);

View File

@@ -641,6 +641,16 @@ static struct phy_driver realtek_drvs[] = {
.resume = rtl821x_resume,
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
}, {
PHY_ID_MATCH_EXACT(0x001cc878),
.name = "RTL8211F-VD Gigabit Ethernet",
.config_init = &rtl8211f_config_init,
.ack_interrupt = &rtl8211f_ack_interrupt,
.config_intr = &rtl8211f_config_intr,
.suspend = genphy_suspend,
.resume = rtl821x_resume,
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
}, {
.name = "Generic FE-GE Realtek PHY",
.match_phy_device = rtlgen_match_phy_device,

View File

@@ -49,6 +49,8 @@ source "drivers/net/wireless/ti/Kconfig"
source "drivers/net/wireless/zydas/Kconfig"
source "drivers/net/wireless/quantenna/Kconfig"
source "drivers/net/wireless/rtl8723ds/Kconfig"
source "drivers/net/wireless/bcmdhd.101.10.361.x/Kconfig"
source "drivers/net/wireless/aic8800/Kconfig"
config PCMCIA_RAYCS
tristate "Aviator/Raytheon 2.4GHz wireless support"

View File

@@ -31,3 +31,7 @@ obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
obj-$(CONFIG_VIRT_WIFI) += virt_wifi.o
obj-$(CONFIG_RTL8723DS) += rtl8723ds/
obj-$(CONFIG_BCMDHD) += bcmdhd.101.10.361.x/
obj-$(CONFIG_AIC_WLAN_SUPPORT) += aic8800/

View File

@@ -0,0 +1,18 @@
config AIC_WLAN_SUPPORT
bool "AIC wireless Support"
default n
help
This is support for aic wireless chip.
config AIC_FW_PATH
depends on AIC_WLAN_SUPPORT
string "Firmware & config file path"
#default "/vendor/etc/firmware"
default "/lib/firmware/aic8800"
help
Path to the firmware & config file.
if AIC_WLAN_SUPPORT
source "drivers/net/wireless/aic8800/aic8800_fdrv/Kconfig"
source "drivers/net/wireless/aic8800/aic8800_btlpm/Kconfig"
endif

View File

@@ -0,0 +1,70 @@
obj-$(CONFIG_AIC8800_BTLPM_SUPPORT) += aic8800_btlpm/
obj-$(CONFIG_AIC8800_WLAN_SUPPORT) += aic8800_fdrv/
obj-$(CONFIG_AIC_WLAN_SUPPORT) += aic8800_bsp/
# Platform support list
CONFIG_PLATFORM_ROCKCHIP ?= n
CONFIG_PLATFORM_ALLWINNER ?= n
CONFIG_PLATFORM_AMLOGIC ?= n
CONFIG_PLATFORM_UBUNTU ?= y
ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y)
#KDIR = /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/kernel
#ARCH = arm
#CROSS_COMPILE = /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
KDIR = /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/kernel
ARCH = arm
CROSS_COMPILE = /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
#KDIR = /home/yaya/E/Rockchip/3399/rk3399-android-10/kernel
#ARCH = arm64
#CROSS_COMPILE = /home/yaya/E/Rockchip/3399/rk3399-android-10/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
ccflags-y += -DANDROID_PLATFORM
ccflags-y += -DCONFIG_PLATFORM_ROCKCHIP
endif
ifeq ($(CONFIG_PLATFORM_ALLWINNER), y)
KDIR = /home/yaya/E/Allwinner/R818/R818/AndroidQ/lichee/kernel/linux-4.9
ARCH = arm64
CROSS_COMPILE = /home/yaya/E/Allwinner/R818/R818/AndroidQ/lichee/out/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
ccflags-y += -DANDROID_PLATFORM
endif
ifeq ($(CONFIG_PLATFORM_AMLOGIC), y)
ccflags-y += -DANDROID_PLATFORM
ARCH = arm
CROSS_COMPILE = /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androidkernel-
KDIR = /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/out/target/product/u202/obj/KERNEL_OBJ/
endif
ifeq ($(CONFIG_PLATFORM_UBUNTU), y)
KDIR = /lib/modules/$(shell uname -r)/build
PWD = $(shell pwd)
KVER = $(shell uname -r)
MODDESTDIR = /lib/modules/$(KVER)/kernel/drivers/net/wireless/aic8800
ARCH = x86_64
CROSS_COMPILE =
endif
all: modules
modules:
make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
install:
mkdir -p $(MODDESTDIR)
install -p -m 644 aic8800_bsp/aic8800_bsp.ko $(MODDESTDIR)/
install -p -m 644 aic8800_fdrv/aic8800_fdrv.ko $(MODDESTDIR)/
install -p -m 644 aic8800_btlpm/aic8800_btlpm.ko $(MODDESTDIR)/
/sbin/depmod -a ${KVER}
uninstall:
rm -rfv $(MODDESTDIR)/aic8800_bsp.ko
rm -rfv $(MODDESTDIR)/aic8800_fdrv.ko
rm -rfv $(MODDESTDIR)/aic8800_btlpm.ko
/sbin/depmod -a ${KVER}
clean:
cd aic8800_bsp/;make clean;cd ..
cd aic8800_fdrv/;make clean;cd ..
cd aic8800_btlpm/;make clean;cd ..
rm -rf modules.order Module.symvers .tmp_versions/

View File

@@ -0,0 +1,141 @@
CONFIG_SDIO_SUPPORT := y
CONFIG_SDIO_PWRCTRL := y
#CONFIG_AIC_FW_PATH = "/vendor/etc/firmware"
CONFIG_AIC_FW_PATH = "/lib/firmware/aic8800"
export CONFIG_AIC_FW_PATH
ccflags-y += -DCONFIG_AIC_FW_PATH=\"$(CONFIG_AIC_FW_PATH)\"
MODULE_NAME := aic8800_bsp
ifeq ($(CONFIG_SDIO_SUPPORT), y)
ccflags-y += -DAICWF_SDIO_SUPPORT
ccflags-$(CONFIG_SDIO_PWRCTRL) += -DCONFIG_SDIO_PWRCTRL
endif
CONFIG_GPIO_WAKEUP = n
CONFIG_LINK_DET_5G = y
CONFIG_MCU_MESSAGE = n
CONFIG_FIRMWARE_ARRAY = n
# Need to set fw path in BOARD_KERNEL_CMDLINE
CONFIG_USE_FW_REQUEST = n
CONFIG_FDRV_NO_REG_SDIO = n
CONFIG_VRF_DCDC_MODE = y
CONFIG_OOB = n
CONFIG_PREALLOC_TXQ = y
CONFIG_ONE_TXQ = n
CONFIG_DPD = n
CONFIG_FORCE_DPD_CALIB = n
ccflags-$(CONFIG_GPIO_WAKEUP) += -DCONFIG_GPIO_WAKEUP
ccflags-$(CONFIG_LINK_DET_5G) += -DCONFIG_LINK_DET_5G
ccflags-$(CONFIG_MCU_MESSAGE) += -DCONFIG_MCU_MESSAGE
ccflags-$(CONFIG_FIRMWARE_ARRAY) += -DCONFIG_FIRMWARE_ARRAY
ccflags-$(CONFIG_USE_FW_REQUEST) += -DCONFIG_USE_FW_REQUEST
ccflags-$(CONFIG_FDRV_NO_REG_SDIO) += -DCONFIG_FDRV_NO_REG_SDIO
ccflags-$(CONFIG_VRF_DCDC_MODE) += -DCONFIG_VRF_DCDC_MODE
ccflags-$(CONFIG_OOB) += -DCONFIG_OOB
ccflags-$(CONFIG_PREALLOC_TXQ) += -DCONFIG_PREALLOC_TXQ
ccflags-$(CONFIG_ONE_TXQ) += -DCONFIG_ONE_TXQ
ccflags-$(CONFIG_DPD) += -DCONFIG_DPD
ccflags-$(CONFIG_FORCE_DPD_CALIB) += -DCONFIG_FORCE_DPD_CALIB -DCONFIG_DPD
obj-m := $(MODULE_NAME).o
$(MODULE_NAME)-y := \
aic8800dc_compat.o \
aic8800d80_compat.o \
aic_bsp_main.o \
aic_bsp_driver.o \
aicsdio.o \
aicsdio_txrxif.o \
md5.o
$(MODULE_NAME)-$(CONFIG_PREALLOC_TXQ) += aicwf_txq_prealloc.o
ifeq ($(CONFIG_FIRMWARE_ARRAY),y)
$(MODULE_NAME)-y += aicwf_firmware_array.o
endif
# Platform support list
CONFIG_PLATFORM_ROCKCHIP ?= n
CONFIG_PLATFORM_ALLWINNER ?=n
CONFIG_PLATFORM_INGENIC_T20 ?= n
CONFIG_PLATFORM_AMLOGIC ?= n
CONFIG_PLATFORM_UBUNTU ?= y
ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y)
ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP
#KDIR ?= /home/yaya/E/Rockchip/3399/rk3399-android-10/kernel
#ARCH ?= arm64
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3399/rk3399-android-10/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
#KDIR ?= /home/yaya/E/Rockchip/3288/Android10/kernel/kernel/
#ARCH ?= arm
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3288/Android10/tool/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
#KDIR ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/kernel
#ARCH ?= arm
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
#KDIR ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/kernel
#ARCH ?= arm
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
#KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel
#KDIR ?= /home/yaya/E/Rockchip/3566/oudu/kernel
#KDIR ?= /home/yaya/E/Rockchip/3566/shengteng/kernel
#ARCH ?= arm64
#CROSS_COMPILE ?= ~/E/Rockchip/3566/Android11/rk3566_rk3568_android11_oranth/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
#KDIR ?= /home/yaya/E/Rockchip/3328/Android9/SDK/kernel/
#ARCH ?= arm64
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3328/Android9/SDK/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel
ARCH ?= arm64
CROSS_COMPILE ?= /home/yaya/E/Rockchip/3566/Android11/rk3566_rk3568_android11_oranth/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
endif
ifeq ($(CONFIG_PLATFORM_ALLWINNER), y)
ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER
#KDIR ?= /home/yaya/E/Allwinner/A133/a133-sdk/android/longan/out/kernel/build/
#ARCH ?= arm64
#CROSS_COMPILE ?= /home/yaya/E/Allwinner/A133/a133-sdk/android/longan/out/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
KDIR ?= /home/yaya/E/Allwinner/r818/Android10/lichee/kernel/linux-4.9/
ARCH ?= arm64
CROSS_COMPILE ?= /home/yaya/E/Allwinner/r818/Android10/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-
endif
ifeq ($(CONFIG_PLATFORM_INGENIC_T20), y)
KDIR ?= /home/yaya/E/T40/kernel
ARCH ?= mips
CROSS_COMPILE ?= /home/yaya/E/T40/mips-linux-gnu-ingenic-gcc7.2.0-glibc2.29-fp64/bin/mips-linux-gnu-
endif
ifeq ($(CONFIG_PLATFORM_AMLOGIC), y)
ccflags-$(CONFIG_PLATFORM_AMLOGIC) += -DCONFIG_PLATFORM_AMLOGIC
KDIR ?= /home/aiden/D1/SDK/Amlogic/905x3_a9/android9.0/out/target/product/u202/obj/KERNEL_OBJ/
ARCH ?= arm
CROSS_COMPILE ?= /home/aiden/D1/SDK/Amlogic/905x3_a9/android9.0/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-
endif
ifeq ($(CONFIG_PLATFORM_UBUNTU), y)
ccflags-$(CONFIG_PLATFORM_UBUNTU) += -DCONFIG_PLATFORM_UBUNTU
KDIR ?= /lib/modules/$(shell uname -r)/build
PWD ?= $(shell pwd)
KVER ?= $(shell uname -r)
MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/
ARCH ?= x86_64
CROSS_COMPILE ?=
endif
all: modules
modules:
make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
install:
mkdir -p $(MODDESTDIR)
install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR)
/sbin/depmod -a ${KVER}
uninstall:
rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko
/sbin/depmod -a ${KVER}
clean:
rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk built-in.a

View File

@@ -0,0 +1,200 @@
#include "aic8800d80_compat.h"
#include "aic_bsp_driver.h"
extern struct aicbsp_info_t aicbsp_info;
extern int adap_test;
typedef u32 (*array2_tbl_t)[2];
#define AIC_PATCH_MAGIG_NUM 0x48435450 // "PTCH"
#define AIC_PATCH_MAGIG_NUM_2 0x50544348 // "HCTP"
#define AIC_PATCH_BLOCK_MAX 4
typedef struct {
uint32_t magic_num;
uint32_t pair_start;
uint32_t magic_num_2;
uint32_t pair_count;
uint32_t block_dst[AIC_PATCH_BLOCK_MAX];
uint32_t block_src[AIC_PATCH_BLOCK_MAX];
uint32_t block_size[AIC_PATCH_BLOCK_MAX]; // word count
} aic_patch_t;
#define AIC_PATCH_OFST(mem) ((size_t) &((aic_patch_t *)0)->mem)
#define AIC_PATCH_ADDR(mem) ((u32)(aic_patch_str_base + AIC_PATCH_OFST(mem)))
u32 aicbsp_syscfg_tbl_8800d80[][2] = {
};
int aicbsp_system_config_8800d80(struct aic_sdio_dev *sdiodev)
{
int syscfg_num = sizeof(aicbsp_syscfg_tbl_8800d80) / sizeof(u32) / 2;
int ret, cnt;
for (cnt = 0; cnt < syscfg_num; cnt++) {
ret = rwnx_send_dbg_mem_write_req(sdiodev, aicbsp_syscfg_tbl_8800d80[cnt][0], aicbsp_syscfg_tbl_8800d80[cnt][1]);
if (ret) {
printk("%x write fail: %d\n", aicbsp_syscfg_tbl_8800d80[cnt][0], ret);
return ret;
}
}
return 0;
}
u32 adaptivity_patch_tbl_8800d80[][2] = {
{0x000C, 0x0000320A}, //linkloss_thd
{0x009C, 0x00000000}, //ac_param_conf
{0x0168, 0x00010000}, //tx_adaptivity_en
};
u32 patch_tbl_8800d80[][2] = {
#ifdef USE_5G
{0x00b4, 0xf3010001},
#else
{0x00b4, 0xf3010000},
#endif
};
#ifdef CONFIG_OOB
// for 8800d40/d80 map data1 isr to gpiob1
u32 gpio_cfg_tbl_8800d40d80[][2] = {
{0x40504084, 0x00000006},
{0x40500040, 0x00000000},
{0x40100030, 0x00000001},
{0x40241020, 0x00000001},
{0x40240030, 0x00000004},
{0x40240020, 0x03020700},
};
#endif
int aicwifi_sys_config_8800d80(struct aic_sdio_dev *sdiodev)
{
#ifdef CONFIG_OOB
int ret, cnt;
int gpiocfg_num = sizeof(gpio_cfg_tbl_8800d40d80) / sizeof(u32) / 2;
for (cnt = 0; cnt < gpiocfg_num; cnt++) {
ret = rwnx_send_dbg_mem_write_req(sdiodev, gpio_cfg_tbl_8800d40d80[cnt][0], gpio_cfg_tbl_8800d40d80[cnt][1]);
if (ret) {
printk("%x write fail: %d\n", gpio_cfg_tbl_8800d40d80[cnt][0], ret);
return ret;
}
}
#endif
return 0;
}
int aicwifi_patch_config_8800d80(struct aic_sdio_dev *sdiodev)
{
const u32 rd_patch_addr = RAM_FMAC_FW_ADDR + 0x0198;
u32 aic_patch_addr;
u32 config_base, aic_patch_str_base;
uint32_t start_addr = 0x0016F800;
u32 patch_addr = start_addr;
u32 patch_cnt = sizeof(patch_tbl_8800d80)/sizeof(u32)/2;
struct dbg_mem_read_cfm rd_patch_addr_cfm;
int ret = 0;
int cnt = 0;
//adap test
int adap_patch_cnt = 0;
if (adap_test) {
adap_patch_cnt = sizeof(adaptivity_patch_tbl_8800d80)/sizeof(u32)/2;
}
aic_patch_addr = rd_patch_addr + 8;
ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_patch_addr, &rd_patch_addr_cfm);
if (ret) {
printk("patch rd fail\n");
return ret;
}
config_base = rd_patch_addr_cfm.memdata;
ret = rwnx_send_dbg_mem_read_req(sdiodev, aic_patch_addr, &rd_patch_addr_cfm);
if (ret) {
printk("patch str rd fail\n");
return ret;
}
aic_patch_str_base = rd_patch_addr_cfm.memdata;
ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(magic_num), AIC_PATCH_MAGIG_NUM);
if (ret) {
printk("0x%x write fail\n", AIC_PATCH_ADDR(magic_num));
return ret;
}
ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(magic_num_2), AIC_PATCH_MAGIG_NUM_2);
if (ret) {
printk("0x%x write fail\n", AIC_PATCH_ADDR(magic_num_2));
return ret;
}
ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(pair_start), patch_addr);
if (ret) {
printk("0x%x write fail\n", AIC_PATCH_ADDR(pair_start));
return ret;
}
ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(pair_count), patch_cnt + adap_patch_cnt);
if (ret) {
printk("0x%x write fail\n", AIC_PATCH_ADDR(pair_count));
return ret;
}
for (cnt = 0; cnt < patch_cnt; cnt++) {
ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, patch_tbl_8800d80[cnt][0]+config_base);
if (ret) {
printk("%x write fail\n", start_addr+8*cnt);
return ret;
}
ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, patch_tbl_8800d80[cnt][1]);
if (ret) {
printk("%x write fail\n", start_addr+8*cnt+4);
return ret;
}
}
if (adap_test){
int tmp_cnt = patch_cnt + adap_patch_cnt;
for (cnt = patch_cnt; cnt < tmp_cnt; cnt++) {
int tbl_idx = cnt - patch_cnt;
ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, adaptivity_patch_tbl_8800d80[tbl_idx][0]+config_base);
if(ret) {
printk("%x write fail\n", start_addr+8*cnt);
return ret;
}
ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, adaptivity_patch_tbl_8800d80[tbl_idx][1]);
if(ret) {
printk("%x write fail\n", start_addr+8*cnt+4);
return ret;
}
}
}
ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[0]), 0);
if (ret) {
printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[0]), ret);
return ret;
}
ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[1]), 0);
if (ret) {
printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[1]), ret);
return ret;
}
ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[2]), 0);
if (ret) {
printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[2]), ret);
return ret;
}
ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[3]), 0);
if (ret) {
printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[3]), ret);
return ret;
}
return 0;
}

View File

@@ -0,0 +1,24 @@
#ifndef _AIC8800D80_COMPAT_H_
#define _AIC8800D80_COMPAT_H_
#include "aicsdio.h"
/*typedef u32 (*array2_tbl_t)[2];
typedef uint8_t u8_l;
typedef int8_t s8_l;
typedef bool bool_l;
typedef uint16_t u16_l;
typedef int16_t s16_l;
typedef uint32_t u32_l;
typedef int32_t s32_l;
typedef uint64_t u64_l;*/
int aicbsp_system_config_8800d80(struct aic_sdio_dev *sdiodev);
int aicwifi_sys_config_8800d80(struct aic_sdio_dev *sdiodev);
int aicwifi_patch_config_8800d80(struct aic_sdio_dev *sdiodev);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
#ifndef _AIC8800DC_COMPAT_H_
#define _AIC8800DC_COMPAT_H_
#include "aicsdio.h"
typedef u32 (*array2_tbl_t)[2];
typedef u32 (*array3_tbl_t)[3];
typedef uint8_t u8_l;
typedef int8_t s8_l;
typedef bool bool_l;
typedef uint16_t u16_l;
typedef int16_t s16_l;
typedef uint32_t u32_l;
typedef int32_t s32_l;
typedef uint64_t u64_l;
extern u8 chip_sub_id;
extern u8 chip_mcu_id;
#define DPD_RESULT_SIZE_8800DC 1880
#define FW_PATH_MAX_LEN 200
void aicwf_patch_config_8800dc(struct aic_sdio_dev *rwnx_hw);
void system_config_8800dc(struct aic_sdio_dev *rwnx_hw);
int aicwf_misc_ram_init_8800dc(struct aic_sdio_dev *sdiodev);
#ifdef CONFIG_DPD
int aicwf_dpd_calib_8800dc(struct aic_sdio_dev *sdiodev, uint32_t *dpd_res);
int aicwf_dpd_result_load_8800dc(struct aic_sdio_dev *sdiodev);
int aicwf_dpd_result_write_8800dc(void *buf, int buf_len);
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,535 @@
/**
******************************************************************************
*
* rwnx_cmds.h
*
* Copyright (C) RivieraWaves 2014-2019
*
******************************************************************************
*/
#ifndef _AIC_BSP_DRIVER_H
#define _AIC_BSP_DRIVER_H
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/module.h>
#include "aic_bsp_export.h"
#define RWNX_80211_CMD_TIMEOUT_MS 3000//500//300
#define RWNX_CMD_FLAG_NONBLOCK BIT(0)
#define RWNX_CMD_FLAG_REQ_CFM BIT(1)
#define RWNX_CMD_FLAG_WAIT_PUSH BIT(2)
#define RWNX_CMD_FLAG_WAIT_ACK BIT(3)
#define RWNX_CMD_FLAG_WAIT_CFM BIT(4)
#define RWNX_CMD_FLAG_DONE BIT(5)
/* ATM IPC design makes it possible to get the CFM before the ACK,
* otherwise this could have simply been a state enum */
#define RWNX_CMD_WAIT_COMPLETE(flags) \
(!(flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_CFM)))
#define RWNX_CMD_MAX_QUEUED 8
#define IPC_E2A_MSG_PARAM_SIZE 256
#define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__
/* message levels */
#define LOGERROR 0x0001
#define LOGINFO 0x0002
#define LOGTRACE 0x0004
#define LOGDEBUG 0x0008
#define LOGDATA 0x0010
extern int aicwf_dbg_level_bsp;
#define AICWF_LOG "AICWFDBG("
#define AICWFDBG(level, args, arg...) \
do { \
if (aicwf_dbg_level_bsp & level) { \
printk(AICWF_LOG#level")\t" args, ##arg); \
} \
} while (0)
#define RWNX_DBG(fmt, ...) \
do { \
if (aicwf_dbg_level_bsp & LOGTRACE) { \
printk(AICWF_LOG"LOGTRACE)\t"fmt , ##__VA_ARGS__); \
} \
} while (0)
/// Message structure for MSGs from Emb to App
struct ipc_e2a_msg {
u16 id; ///< Message id.
u16 dummy_dest_id;
u16 dummy_src_id;
u16 param_len; ///< Parameter embedded struct length.
u32 pattern; ///< Used to stamp a valid MSG buffer
u32 param[IPC_E2A_MSG_PARAM_SIZE]; ///< Parameter embedded struct. Must be word-aligned.
};
typedef u16 lmac_msg_id_t;
typedef u16 lmac_task_id_t;
struct lmac_msg {
lmac_msg_id_t id; ///< Message id.
lmac_task_id_t dest_id; ///< Destination kernel identifier.
lmac_task_id_t src_id; ///< Source kernel identifier.
u16 param_len; ///< Parameter embedded struct length.
u32 param[]; ///< Parameter embedded struct. Must be word-aligned.
};
#define rwnx_cmd_e2amsg ipc_e2a_msg
#define rwnx_cmd_a2emsg lmac_msg
#define RWNX_CMD_A2EMSG_LEN(m) (sizeof(struct lmac_msg) + m->param_len)
#define RWNX_CMD_E2AMSG_LEN_MAX (IPC_E2A_MSG_PARAM_SIZE * 4)
static inline void put_u16(u8 *buf, u16 data)
{
buf[0] = (u8)(data&0x00ff);
buf[1] = (u8)((data >> 8)&0x00ff);
}
enum rwnx_cmd_mgr_state {
RWNX_CMD_MGR_STATE_DEINIT,
RWNX_CMD_MGR_STATE_INITED,
RWNX_CMD_MGR_STATE_CRASHED,
};
struct rwnx_cmd {
struct list_head list;
lmac_msg_id_t id;
lmac_msg_id_t reqid;
struct rwnx_cmd_a2emsg *a2e_msg;
char *e2a_msg;
u32 tkn;
u16 flags;
struct completion complete;
u32 result;
};
struct aic_sdio_dev;
struct rwnx_cmd;
typedef int (*msg_cb_fct)(struct rwnx_cmd *cmd, struct rwnx_cmd_e2amsg *msg);
struct rwnx_cmd_mgr {
enum rwnx_cmd_mgr_state state;
spinlock_t lock;
u32 next_tkn;
u32 queue_sz;
u32 max_queue_sz;
spinlock_t cb_lock;
void *sdiodev;
struct list_head cmds;
int (*queue)(struct rwnx_cmd_mgr *, struct rwnx_cmd *);
int (*llind)(struct rwnx_cmd_mgr *, struct rwnx_cmd *);
int (*msgind)(struct rwnx_cmd_mgr *, struct rwnx_cmd_e2amsg *, msg_cb_fct);
void (*print)(struct rwnx_cmd_mgr *);
void (*drain)(struct rwnx_cmd_mgr *);
struct work_struct cmdWork;
struct workqueue_struct *cmd_wq;
};
void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr);
void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr);
int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd);
void rwnx_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len);
enum {
TASK_NONE = (u8) -1,
// MAC Management task.
TASK_MM = 0,
// DEBUG task
TASK_DBG,
/// SCAN task
TASK_SCAN,
/// TDLS task
TASK_TDLS,
/// SCANU task
TASK_SCANU,
/// ME task
TASK_ME,
/// SM task
TASK_SM,
/// APM task
TASK_APM,
/// BAM task
TASK_BAM,
/// MESH task
TASK_MESH,
/// RXU task
TASK_RXU,
// This is used to define the last task that is running on the EMB processor
TASK_LAST_EMB = TASK_RXU,
// nX API task
TASK_API,
TASK_MAX,
};
#define LMAC_FIRST_MSG(task) ((lmac_msg_id_t)((task) << 10))
#define DRV_TASK_ID 100
#define MSG_I(msg) ((msg) & ((1<<10)-1))
#define MSG_T(msg) ((lmac_task_id_t)((msg) >> 10))
enum dbg_msg_tag {
/// Memory read request
DBG_MEM_READ_REQ = LMAC_FIRST_MSG(TASK_DBG),
/// Memory read confirm
DBG_MEM_READ_CFM,
/// Memory write request
DBG_MEM_WRITE_REQ,
/// Memory write confirm
DBG_MEM_WRITE_CFM,
/// Module filter request
DBG_SET_MOD_FILTER_REQ,
/// Module filter confirm
DBG_SET_MOD_FILTER_CFM,
/// Severity filter request
DBG_SET_SEV_FILTER_REQ,
/// Severity filter confirm
DBG_SET_SEV_FILTER_CFM,
/// LMAC/MAC HW fatal error indication
DBG_ERROR_IND,
/// Request to get system statistics
DBG_GET_SYS_STAT_REQ,
/// COnfirmation of system statistics
DBG_GET_SYS_STAT_CFM,
/// Memory block write request
DBG_MEM_BLOCK_WRITE_REQ,
/// Memory block write confirm
DBG_MEM_BLOCK_WRITE_CFM,
/// Start app request
DBG_START_APP_REQ,
/// Start app confirm
DBG_START_APP_CFM,
/// Start npc request
DBG_START_NPC_REQ,
/// Start npc confirm
DBG_START_NPC_CFM,
/// Memory mask write request
DBG_MEM_MASK_WRITE_REQ,
/// Memory mask write confirm
DBG_MEM_MASK_WRITE_CFM,
DBG_RFTEST_CMD_REQ,
DBG_RFTEST_CMD_CFM,
DBG_BINDING_REQ,
DBG_BINDING_CFM,
DBG_BINDING_IND,
DBG_CUSTOM_MSG_REQ,
DBG_CUSTOM_MSG_CFM,
DBG_CUSTOM_MSG_IND,
DBG_GPIO_WRITE_REQ,
DBG_GPIO_WRITE_CFM,
/// Max number of Debug messages
DBG_MAX,
};
enum {
HOST_START_APP_AUTO = 1,
HOST_START_APP_CUSTOM,
HOST_START_APP_FNCALL = 4,
HOST_START_APP_DUMMY = 5,
};
struct dbg_mem_block_write_req {
u32 memaddr;
u32 memsize;
u32 memdata[1024 / sizeof(u32)];
};
/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_WRITE_CFM message.
struct dbg_mem_block_write_cfm {
u32 wstatus;
};
/// Structure containing the parameters of the @ref DBG_MEM_WRITE_REQ message.
struct dbg_mem_write_req {
u32 memaddr;
u32 memdata;
};
/// Structure containing the parameters of the @ref DBG_MEM_WRITE_CFM message.
struct dbg_mem_write_cfm {
u32 memaddr;
u32 memdata;
};
/// Structure containing the parameters of the @ref DBG_MEM_READ_REQ message.
struct dbg_mem_read_req {
u32 memaddr;
};
/// Structure containing the parameters of the @ref DBG_MEM_READ_CFM message.
struct dbg_mem_read_cfm {
u32 memaddr;
u32 memdata;
};
/// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_REQ message.
struct dbg_mem_mask_write_req {
u32 memaddr;
u32 memmask;
u32 memdata;
};
/// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_CFM message.
struct dbg_mem_mask_write_cfm {
u32 memaddr;
u32 memdata;
};
/// Structure containing the parameters of the @ref DBG_START_APP_REQ message.
struct dbg_start_app_req {
u32 bootaddr;
u32 boottype;
};
/// Structure containing the parameters of the @ref DBG_START_APP_CFM message.
struct dbg_start_app_cfm {
u32 bootstatus;
};
int aicwf_plat_patch_load_8800dc(struct aic_sdio_dev *sdiodev);
int aicwf_plat_rftest_load_8800dc(struct aic_sdio_dev *sdiodev);
#ifdef CONFIG_DPD
int aicwf_plat_calib_load_8800dc(struct aic_sdio_dev *sdiodev);
#endif
int rwnx_load_firmware(u32 **fw_buf, const char *name, struct device *device);
int aicwf_patch_table_load(struct aic_sdio_dev *rwnx_hw, char *filename);
int rwnx_send_dbg_mem_read_req(struct aic_sdio_dev *sdiodev, u32 mem_addr,
struct dbg_mem_read_cfm *cfm);
int rwnx_send_dbg_mem_block_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr,
u32 mem_size, u32 *mem_data);
int rwnx_send_dbg_mem_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, u32 mem_data);
int rwnx_send_dbg_mem_mask_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr,
u32 mem_mask, u32 mem_data);
int rwnx_send_dbg_start_app_req(struct aic_sdio_dev *sdiodev, u32 boot_addr, u32 boot_type, struct dbg_start_app_cfm *start_app_cfm);
int rwnx_plat_bin_fw_upload_android(struct aic_sdio_dev *sdiodev, u32 fw_addr, const char *filename);
void rwnx_rx_handle_msg(struct aic_sdio_dev *sdiodev, struct ipc_e2a_msg *msg);
int aicbsp_platform_init(struct aic_sdio_dev *sdiodev);
void aicbsp_platform_deinit(struct aic_sdio_dev *sdiodev);
int aicbsp_driver_fw_init(struct aic_sdio_dev *sdiodev);
#ifdef CONFIG_DPD
int is_file_exist(char* name);
#endif
int aicbsp_resv_mem_init(void);
int aicbsp_resv_mem_deinit(void);
#define AICBSP_FW_PATH CONFIG_AIC_FW_PATH
#define AICBSP_FW_PATH_MAX 200
#define RAM_FMAC_FW_ADDR 0x00120000
#define FW_RAM_ADID_BASE_ADDR 0x00161928
#define FW_RAM_ADID_BASE_ADDR_U03 0x00161928
#define FW_RAM_PATCH_BASE_ADDR 0x00100000
#define RAM_8800DC_U01_ADID_ADDR 0x00101788
#define RAM_8800DC_U02_ADID_ADDR 0x001017d8
#define RAM_8800DC_FW_PATCH_ADDR 0x00184000
#define FW_RESET_START_ADDR 0x40500128
#define FW_RESET_START_VAL 0x40
#define FW_ADID_FLAG_ADDR 0x40500150
#define FW_ADID_FLAG_VAL 0x01
#define FW_RAM_ADID_BASE_ADDR_8800D80 0x002017E0
#define FW_RAM_PATCH_BASE_ADDR_8800D80 0x0020B2B0
#define FW_RAM_ADID_BASE_ADDR_8800D80_U02 0x00201940
#define FW_RAM_PATCH_BASE_ADDR_8800D80_U02 0x0020b43c
#define AICBT_PT_TAG "AICBT_PT_TAG"
/*****************************************************************************
* Addresses within RWNX_ADDR_CPU
*****************************************************************************/
#define RAM_LMAC_FW_ADDR 0x00150000
#define ROM_FMAC_FW_ADDR 0x00010000
#define ROM_FMAC_PATCH_ADDR 0x00180000
#define RWNX_MAC_CALIB_BASE_NAME_8800DC "fmacfw_calib_8800dc"
#define RWNX_MAC_CALIB_NAME_8800DC_U02 RWNX_MAC_CALIB_BASE_NAME_8800DC"_u02.bin"
#ifdef CONFIG_DPD
#define ROM_FMAC_CALIB_ADDR 0x00130000
#define FW_DPDRESULT_NAME_8800DC "aic_dpdresult_8800dc.bin"
#endif
#define RWNX_MAC_FW_RF_BASE_NAME_8800DC "lmacfw_rf_8800dc.bin"
#ifdef CONFIG_FOR_IPCOM
#define RWNX_MAC_PATCH_BASE_NAME_8800DC "fmacfw_patch_8800dc_ipc"
#define RWNX_MAC_PATCH_NAME2_8800DC RWNX_MAC_PATCH_BASE_NAME_8800DC".bin"
#else
#define RWNX_MAC_PATCH_BASE_NAME_8800DC "fmacfw_patch_8800dc"
#define RWNX_MAC_PATCH_NAME2_8800DC RWNX_MAC_PATCH_BASE_NAME_8800DC".bin"
#define RWNX_MAC_PATCH_NAME2_8800DC_U02 RWNX_MAC_PATCH_BASE_NAME_8800DC"_u02.bin"
#endif
#define RWNX_MAC_PATCH_TABLE_NAME_8800DC "fmacfw_patch_tbl_8800dc"
#define RWNX_MAC_PATCH_TABLE_8800DC RWNX_MAC_PATCH_TABLE_NAME_8800DC ".bin"
#define RWNX_MAC_PATCH_TABLE_8800DC_U02 RWNX_MAC_PATCH_TABLE_NAME_8800DC "_u02.bin"
#define RWNX_MAC_RF_PATCH_BASE_NAME_8800DC "fmacfw_rf_patch_8800dc"
#define RWNX_MAC_RF_PATCH_NAME_8800DC RWNX_MAC_RF_PATCH_BASE_NAME_8800DC".bin"
#define FW_USERCONFIG_NAME_8800DC "aic_userconfig_8800dc.txt"
enum {
FW_NORMAL_MODE = 0,
FW_RFTEST_MODE = 1,
FW_BLE_SCAN_WAKEUP_MODE = 2,
FW_M2D_OTA_MODE = 3,
FW_DPDCALIB_MODE = 4,
FW_BLE_SCAN_AD_FILTER_MODE = 5,
};
enum aicbt_patch_table_type {
AICBT_PT_INF = 0x00,
AICBT_PT_TRAP = 0x1,
AICBT_PT_B4,
AICBT_PT_BTMODE,
AICBT_PT_PWRON,
AICBT_PT_AF,
AICBT_PT_VER,
};
enum aicbt_btport_type {
AICBT_BTPORT_NULL,
AICBT_BTPORT_MB,
AICBT_BTPORT_UART,
};
/* btmode
* used for force bt mode,if not AICBSP_MODE_NULL
* efuse valid and vendor_info will be invalid, even has beed set valid
*/
enum aicbt_btmode_type {
AICBT_BTMODE_BT_ONLY_SW = 0x0, // bt only mode with switch
AICBT_BTMODE_BT_WIFI_COMBO, // wifi/bt combo mode
AICBT_BTMODE_BT_ONLY, // bt only mode without switch
AICBT_BTMODE_BT_ONLY_TEST, // bt only test mode
AICBT_BTMODE_BT_WIFI_COMBO_TEST, // wifi/bt combo test mode
AICBT_BTMODE_BT_ONLY_COANT, // bt only mode with no external switch
AICBT_MODE_NULL = 0xFF, // invalid value
};
/* uart_baud
* used for config uart baud when btport set to uart,
* otherwise meaningless
*/
enum aicbt_uart_baud_type {
AICBT_UART_BAUD_115200 = 115200,
AICBT_UART_BAUD_921600 = 921600,
AICBT_UART_BAUD_1_5M = 1500000,
AICBT_UART_BAUD_3_25M = 3250000,
};
enum aicbt_uart_flowctrl_type {
AICBT_UART_FLOWCTRL_DISABLE = 0x0, // uart without flow ctrl
AICBT_UART_FLOWCTRL_ENABLE, // uart with flow ctrl
};
enum aicbsp_cpmode_type {
AICBSP_CPMODE_WORK,
AICBSP_CPMODE_TEST,
AICBSP_CPMODE_MAX,
};
enum chip_rev {
CHIP_REV_U01 = 1,
CHIP_REV_U02 = 3,
CHIP_REV_U03 = 7,
CHIP_REV_U04 = 7,
};
///aic bt tx pwr lvl :lsb->msb: first byte, min pwr lvl; second byte, max pwr lvl;
///pwr lvl:20(min), 30 , 40 , 50 , 60(max)
#define AICBT_TXPWR_LVL 0x00006020
#define AICBT_TXPWR_LVL_8800dc 0x00006f2f
#define AICBT_TXPWR_LVL_8800d80 0x00006f2f
#define AICBSP_HWINFO_DEFAULT (-1)
#define AICBSP_CPMODE_DEFAULT AICBSP_CPMODE_WORK
#define AICBSP_FWLOG_EN_DEFAULT 0
#define AICBT_BTMODE_DEFAULT AICBT_BTMODE_BT_ONLY_SW
#define AICBT_BTPORT_DEFAULT AICBT_BTPORT_UART
#define AICBT_UART_BAUD_DEFAULT AICBT_UART_BAUD_1_5M
#define AICBT_UART_FC_DEFAULT AICBT_UART_FLOWCTRL_ENABLE
#define AICBT_LPM_ENABLE_DEFAULT 0
#define AICBT_TXPWR_LVL_DEFAULT AICBT_TXPWR_LVL
#define FEATURE_SDIO_CLOCK 50000000 // 0: default, other: target clock rate
#define FEATURE_SDIO_CLOCK_V3 150000000 // 0: default, other: target clock rate
#define FEATURE_SDIO_PHASE 2 // 0: default, 2: 180°
struct aicbt_patch_table {
char *name;
uint32_t type;
uint32_t *data;
uint32_t len;
struct aicbt_patch_table *next;
};
struct aicbt_info_t {
uint32_t btmode;
uint32_t btport;
uint32_t uart_baud;
uint32_t uart_flowctrl;
uint32_t lpm_enable;
uint32_t txpwr_lvl;
};
struct aicbt_patch_info_t {
uint32_t info_len;
uint32_t adid_addrinf;
uint32_t addr_adid;
uint32_t patch_addrinf;
uint32_t addr_patch;
uint32_t reset_addr;
uint32_t reset_val;
uint32_t adid_flag_addr;
uint32_t adid_flag;
};
struct aicbsp_firmware {
const char *desc;
const char *bt_adid;
const char *bt_patch;
const char *bt_table;
const char *wl_fw;
};
struct aicbsp_info_t {
int hwinfo;
int hwinfo_r;
uint32_t cpmode;
uint32_t chip_rev;
bool fwlog_en;
};
extern struct aicbsp_info_t aicbsp_info;
extern struct mutex aicbsp_power_lock;
extern const struct aicbsp_firmware *aicbsp_firmware_list;
extern const struct aicbsp_firmware fw_u02[];
extern const struct aicbsp_firmware fw_u03[];
extern const struct aicbsp_firmware fw_8800dc_u01[];
extern const struct aicbsp_firmware fw_8800dc_u02[];
extern const struct aicbsp_firmware fw_8800d80_u01[];
extern const struct aicbsp_firmware fw_8800d80_u02[];
#endif

View File

@@ -0,0 +1,40 @@
#ifndef __AIC_BSP_EXPORT_H
#define __AIC_BSP_EXPORT_H
#define AICBSP_RESV_MEM_SUPPORT 0
enum aicbsp_subsys {
AIC_BLUETOOTH,
AIC_WIFI,
};
enum aicbsp_pwr_state {
AIC_PWR_OFF,
AIC_PWR_ON,
};
enum skb_buff_id {
AIC_RESV_MEM_TXDATA,
};
struct skb_buff_pool {
uint32_t id;
uint32_t size;
const char *name;
uint8_t used;
struct sk_buff *skb;
};
struct aicbsp_feature_t {
int hwinfo;
uint32_t sdio_clock;
uint8_t sdio_phase;
bool fwlog_en;
};
int aicbsp_set_subsys(int, int);
int aicbsp_get_feature(struct aicbsp_feature_t *feature, char *fw_path);
struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id);
void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id);
#endif

View File

@@ -0,0 +1,361 @@
#include <linux/module.h>
#include <linux/inetdevice.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/platform_device.h>
#include "aic_bsp_driver.h"
#include "rwnx_version_gen.h"
#include "aicwf_txq_prealloc.h"
#define DRV_DESCRIPTION "AIC BSP"
#define DRV_COPYRIGHT "Copyright(c) 2015-2020 AICSemi"
#define DRV_AUTHOR "AICSemi"
#define DRV_VERS_MOD "1.0"
/* int aicwf_dbg_level_bsp = LOGERROR|LOGINFO|LOGDEBUG|LOGTRACE; */
int aicwf_dbg_level_bsp = LOGERROR;
module_param(aicwf_dbg_level_bsp, int, 0660);
static struct platform_device *aicbsp_pdev;
const struct aicbsp_firmware *aicbsp_firmware_list = fw_u02;
const struct aicbsp_firmware fw_u02[] = {
[AICBSP_CPMODE_WORK] = {
.desc = "normal work mode(sdio u02)",
.bt_adid = "fw_adid.bin",
.bt_patch = "fw_patch.bin",
.bt_table = "fw_patch_table.bin",
.wl_fw = "fmacfw.bin"
},
[AICBSP_CPMODE_TEST] = {
.desc = "rf test mode(sdio u02)",
.bt_adid = "fw_adid.bin",
.bt_patch = "fw_patch.bin",
.bt_table = "fw_patch_table.bin",
.wl_fw = "fmacfw_rf.bin"
},
};
const struct aicbsp_firmware fw_u03[] = {
[AICBSP_CPMODE_WORK] = {
.desc = "normal work mode(sdio u03/u04)",
.bt_adid = "fw_adid_u03.bin",
.bt_patch = "fw_patch_u03.bin",
.bt_table = "fw_patch_table_u03.bin",
#ifdef CONFIG_MCU_MESSAGE
.wl_fw = "fmacfw_8800m_custmsg.bin"
#else
.wl_fw = "fmacfw.bin"
#endif
},
[AICBSP_CPMODE_TEST] = {
.desc = "rf test mode(sdio u03/u04)",
.bt_adid = "fw_adid_u03.bin",
.bt_patch = "fw_patch_u03.bin",
.bt_table = "fw_patch_table_u03.bin",
.wl_fw = "fmacfw_rf.bin"
},
};
const struct aicbsp_firmware fw_8800dc_u01[] = {
[AICBSP_CPMODE_WORK] = {
.desc = "normal work mode(sdio u01)",
.bt_adid = "fw_adid_8800dc.bin",
.bt_patch = "fw_patch_8800dc.bin",
.bt_table = "fw_patch_table_8800dc.bin",
.wl_fw = "fmacfw_8800dc.bin"
},
[AICBSP_CPMODE_TEST] = {
.desc = "rf test mode(sdio u01)",
.bt_adid = "fw_adid_8800dc.bin",
.bt_patch = "fw_patch_8800dc.bin",
.bt_table = "fw_patch_table_8800dc.bin",
.wl_fw = "fmacfw_rf_8800dc.bin"
},
};
const struct aicbsp_firmware fw_8800dc_u02[] = {
[AICBSP_CPMODE_WORK] = {
.desc = "normal work mode(8800dc sdio u02)",
.bt_adid = "fw_adid_8800dc_u02.bin",
.bt_patch = "fw_patch_8800dc_u02.bin",
.bt_table = "fw_patch_table_8800dc_u02.bin",
.wl_fw = "fmacfw_patch_8800dc_u02.bin"
},
[AICBSP_CPMODE_TEST] = {
.desc = "rf test mode(8800dc sdio u02)",
.bt_adid = "fw_adid_8800dc_u02.bin",
.bt_patch = "fw_patch_8800dc_u02.bin",
.bt_table = "fw_patch_table_8800dc_u02.bin",
.wl_fw = "lmacfw_rf_8800dc.bin" //u01,u02 lmacfw load same bin
},
};
const struct aicbsp_firmware fw_8800d80_u01[] = {
[AICBSP_CPMODE_WORK] = {
.desc = "normal work mode(8800d80 sdio u01)",
.bt_adid = "fw_adid_8800d80.bin",
.bt_patch = "fw_patch_8800d80.bin",
.bt_table = "fw_patch_table_8800d80.bin",
.wl_fw = "fmacfw_8800d80.bin"
},
[AICBSP_CPMODE_TEST] = {
.desc = "rf test mode(8800d80 sdio u01)",
.bt_adid = "fw_adid_8800d80.bin",
.bt_patch = "fw_patch_8800d80.bin",
.bt_table = "fw_patch_table_8800d80.bin",
.wl_fw = "lmacfw_rf_8800d80.bin"
},
};
const struct aicbsp_firmware fw_8800d80_u02[] = {
[AICBSP_CPMODE_WORK] = {
.desc = "normal work mode(8800d80 sdio u02)",
.bt_adid = "fw_adid_8800d80_u02.bin",
.bt_patch = "fw_patch_8800d80_u02.bin",
.bt_table = "fw_patch_table_8800d80_u02.bin",
.wl_fw = "fmacfw_8800d80_u02.bin"
},
[AICBSP_CPMODE_TEST] = {
.desc = "rf test mode(8800d80 sdio u02)",
.bt_adid = "fw_adid_8800d80_u02.bin",
.bt_patch = "fw_patch_8800d80_u02.bin",
.bt_table = "fw_patch_table_8800d80_u02.bin",
.wl_fw = "lmacfw_rf_8800d80_u02.bin"
},
};
struct aicbsp_info_t aicbsp_info = {
.hwinfo_r = AICBSP_HWINFO_DEFAULT,
.hwinfo = AICBSP_HWINFO_DEFAULT,
.cpmode = AICBSP_CPMODE_DEFAULT,
.fwlog_en = AICBSP_FWLOG_EN_DEFAULT,
};
struct mutex aicbsp_power_lock;
static struct platform_driver aicbsp_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "aic_bsp",
},
//.probe = aicbsp_probe,
//.remove = aicbsp_remove,
};
static ssize_t cpmode_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t count = 0;
uint8_t i = 0;
count += sprintf(&buf[count], "Support mode value:\n");
for (i = 0; i < AICBSP_CPMODE_MAX; i++) {
if (aicbsp_firmware_list[i].desc)
count += sprintf(&buf[count], " %2d: %s\n", i, aicbsp_firmware_list[i].desc);
}
count += sprintf(&buf[count], "Current: %d, firmware info:\n", aicbsp_info.cpmode);
count += sprintf(&buf[count], " BT ADID : %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_adid);
count += sprintf(&buf[count], " BT PATCH: %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_patch);
count += sprintf(&buf[count], " BT TABLE: %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_table);
count += sprintf(&buf[count], " WIFI FW : %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw);
return count;
}
static ssize_t cpmode_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
unsigned long val;
int err = kstrtoul(buf, 0, &val);
if (err)
return err;
if (val >= AICBSP_CPMODE_MAX) {
pr_err("mode value must less than %d\n", AICBSP_CPMODE_MAX);
return -EINVAL;
}
aicbsp_info.cpmode = val;
printk("%s, set mode to: %lu[%s] done\n", __func__, val, aicbsp_firmware_list[val].desc);
return count;
}
static ssize_t hwinfo_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t count = 0;
count += sprintf(&buf[count], "chip hw rev: ");
if (aicbsp_info.hwinfo_r < 0)
count += sprintf(&buf[count], "-1(not avalible)\n");
else
count += sprintf(&buf[count], "0x%02X\n", aicbsp_info.chip_rev);
count += sprintf(&buf[count], "hwinfo read: ");
if (aicbsp_info.hwinfo_r < 0)
count += sprintf(&buf[count], "%d(not avalible), ", aicbsp_info.hwinfo_r);
else
count += sprintf(&buf[count], "0x%02X, ", aicbsp_info.hwinfo_r);
if (aicbsp_info.hwinfo < 0)
count += sprintf(&buf[count], "set: %d(not avalible)\n", aicbsp_info.hwinfo);
else
count += sprintf(&buf[count], "set: 0x%02X\n", aicbsp_info.hwinfo);
return count;
}
static ssize_t hwinfo_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
long val;
int err = kstrtol(buf, 0, &val);
if (err) {
pr_err("invalid input\n");
return err;
}
if ((val == -1) || (val >= 0 && val <= 0xFF)) {
aicbsp_info.hwinfo = val;
} else {
pr_err("invalid values\n");
return -EINVAL;
}
return count;
}
static ssize_t fwdebug_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t count = 0;
count += sprintf(&buf[count], "fw log status: %s\n",
aicbsp_info.fwlog_en ? "on" : "off");
return count;
}
static ssize_t fwdebug_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
long val;
int err = kstrtol(buf, 0, &val);
if (err) {
pr_err("invalid input\n");
return err;
}
if (val > 1 || val < 0) {
pr_err("must be 0 or 1\n");
return -EINVAL;
}
aicbsp_info.fwlog_en = val;
return count;
}
static DEVICE_ATTR(cpmode, S_IRUGO | S_IWUSR,
cpmode_show, cpmode_store);
static DEVICE_ATTR(hwinfo, S_IRUGO | S_IWUSR,
hwinfo_show, hwinfo_store);
static DEVICE_ATTR(fwdebug, S_IRUGO | S_IWUSR,
fwdebug_show, fwdebug_store);
static struct attribute *aicbsp_attributes[] = {
&dev_attr_cpmode.attr,
&dev_attr_hwinfo.attr,
&dev_attr_fwdebug.attr,
NULL,
};
static struct attribute_group aicbsp_attribute_group = {
.name = "aicbsp_info",
.attrs = aicbsp_attributes,
};
int testmode = AICBSP_CPMODE_DEFAULT;
int adap_test = 0;
module_param(testmode, int, 0660);
module_param(adap_test, int, 0660);
static int __init aicbsp_init(void)
{
int ret;
printk("%s\n", __func__);
printk("RELEASE_DATE:%s\r\n", RELEASE_DATE);
aicbsp_info.cpmode = testmode;
aicbsp_resv_mem_init();
ret = platform_driver_register(&aicbsp_driver);
if (ret) {
pr_err("register platform driver failed: %d\n", ret);
return ret;
}
aicbsp_pdev = platform_device_alloc("aic-bsp", -1);
ret = platform_device_add(aicbsp_pdev);
if (ret) {
pr_err("register platform device failed: %d\n", ret);
return ret;
}
ret = sysfs_create_group(&(aicbsp_pdev->dev.kobj), &aicbsp_attribute_group);
if (ret) {
pr_err("register sysfs create group failed!\n");
return ret;
}
mutex_init(&aicbsp_power_lock);
#ifdef CONFIG_PLATFORM_ROCKCHIP
aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_ON);
#endif
return 0;
}
void aicbsp_sdio_exit(void);
extern struct aic_sdio_dev *aicbsp_sdiodev;
static void __exit aicbsp_exit(void)
{
#ifdef CONFIG_PLATFORM_ROCKCHIP
if(aicbsp_sdiodev){
aicbsp_sdio_exit();
}
#endif
sysfs_remove_group(&(aicbsp_pdev->dev.kobj), &aicbsp_attribute_group);
platform_device_del(aicbsp_pdev);
platform_driver_unregister(&aicbsp_driver);
mutex_destroy(&aicbsp_power_lock);
aicbsp_resv_mem_deinit();
#ifdef CONFIG_PREALLOC_TXQ
aicwf_prealloc_txq_free();
#endif
printk("%s\n", __func__);
}
module_init(aicbsp_init);
module_exit(aicbsp_exit);
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERS_MOD);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,147 @@
/**
* aicwf_sdio.h
*
* SDIO function declarations
*
* Copyright (C) AICSemi 2018-2020
*/
#ifndef _AICWF_SDMMC_H_
#define _AICWF_SDMMC_H_
#ifdef AICWF_SDIO_SUPPORT
#include <linux/skbuff.h>
#include <linux/if_ether.h>
#include <linux/ieee80211.h>
#include <linux/semaphore.h>
#include "aic_bsp_driver.h"
#define AICBSP_SDIO_NAME "aicbsp_sdio"
#define SDIOWIFI_FUNC_BLOCKSIZE 512
#define SDIO_VENDOR_ID_AIC 0x8800
#define SDIO_DEVICE_ID_AIC 0x0001
#define SDIOWIFI_BYTEMODE_LEN_REG 0x02
#define SDIOWIFI_INTR_CONFIG_REG 0x04
#define SDIOWIFI_SLEEP_REG 0x05
#define SDIOWIFI_WAKEUP_REG 0x09
#define SDIOWIFI_FLOW_CTRL_REG 0x0A
#define SDIOWIFI_REGISTER_BLOCK 0x0B
#define SDIOWIFI_BYTEMODE_ENABLE_REG 0x11
#define SDIOWIFI_BLOCK_CNT_REG 0x12
#define SDIOWIFI_FLOWCTRL_MASK_REG 0x7F
#define SDIOWIFI_WR_FIFO_ADDR 0x07
#define SDIOWIFI_RD_FIFO_ADDR 0x08
#define SDIOWIFI_INTR_ENABLE_REG_V3 0x00
#define SDIOWIFI_INTR_PENDING_REG_V3 0x01
#define SDIOWIFI_INTR_TO_DEVICE_REG_V3 0x02
#define SDIOWIFI_FLOW_CTRL_Q1_REG_V3 0x03
#define SDIOWIFI_MISC_INT_STATUS_REG_V3 0x04
#define SDIOWIFI_BYTEMODE_LEN_REG_V3 0x05
#define SDIOWIFI_BYTEMODE_LEN_MSB_REG_V3 0x06
#define SDIOWIFI_BYTEMODE_ENABLE_REG_V3 0x07
#define SDIOWIFI_MISC_CTRL_REG_V3 0x08
#define SDIOWIFI_FLOW_CTRL_Q2_REG_V3 0x09
#define SDIOWIFI_CLK_TEST_RESULT_REG_V3 0x0A
#define SDIOWIFI_RD_FIFO_ADDR_V3 0x0F
#define SDIOWIFI_WR_FIFO_ADDR_V3 0x10
#define SDIOCLK_FREE_RUNNING_BIT (1 << 6)
#define SDIOWIFI_PWR_CTRL_INTERVAL 30
#define FLOW_CTRL_RETRY_COUNT 50
#define BUFFER_SIZE 1536
#define TAIL_LEN 4
#define TXQLEN (2048*4)
#define SDIO_SLEEP_ST 0
#define SDIO_ACTIVE_ST 1
typedef enum {
SDIO_TYPE_DATA = 0X00,
SDIO_TYPE_CFG = 0X10,
SDIO_TYPE_CFG_CMD_RSP = 0X11,
SDIO_TYPE_CFG_DATA_CFM = 0X12
} sdio_type;
enum AICWF_IC{
PRODUCT_ID_AIC8801 = 0,
PRODUCT_ID_AIC8800DC,
PRODUCT_ID_AIC8800DW,
PRODUCT_ID_AIC8800D80
};
struct aic_sdio_reg {
u8 bytemode_len_reg;
u8 intr_config_reg;
u8 sleep_reg;
u8 wakeup_reg;
u8 flow_ctrl_reg;
u8 flowctrl_mask_reg;
u8 register_block;
u8 bytemode_enable_reg;
u8 block_cnt_reg;
u8 misc_int_status_reg;
u8 rd_fifo_addr;
u8 wr_fifo_addr;
};
struct aic_sdio_dev {
struct rwnx_cmd_mgr cmd_mgr;
struct sdio_func *func;
struct sdio_func *func_msg;
struct device *dev;
struct aicwf_bus *bus_if;
struct aicwf_rx_priv *rx_priv;
struct aicwf_tx_priv *tx_priv;
u32 state;
#if defined(CONFIG_SDIO_PWRCTRL)
//for sdio pwr ctrl
struct timer_list timer;
uint active_duration;
struct completion pwrctrl_trgg;
struct task_struct *pwrctl_tsk;
spinlock_t pwrctl_lock;
struct semaphore pwrctl_wakeup_sema;
#endif
u16 chipid;
struct aic_sdio_reg sdio_reg;
void (*sdio_hal_irqhandler) (struct sdio_func *func);
};
void *aicbsp_get_drvdata(void *args);
int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val);
void aicwf_sdio_hal_irqhandler(struct sdio_func *func);
void aicwf_sdio_hal_irqhandler_func2(struct sdio_func *func);
#if defined(CONFIG_SDIO_PWRCTRL)
void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration);
int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target);
#endif
void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev);
int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev);
int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev);
void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev);
int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev);
int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, u32 size, u8 msg);
int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count);
void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev);
void aicwf_sdio_release(struct aic_sdio_dev *sdiodev);
void aicbsp_sdio_exit(void);
int aicbsp_sdio_init(void);
void aicbsp_sdio_release(struct aic_sdio_dev *sdiodev);
int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt);
int aicwf_sdio_bustx_thread(void *data);
int aicwf_sdio_busrx_thread(void *data);
int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt);
int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv);
void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv);
void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv *tx_priv);
extern void aicwf_hostif_ready(void);
int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv);
uint8_t crc8_ponl_107(uint8_t *p_buffer, uint16_t cal_size);
#endif /* AICWF_SDIO_SUPPORT */
#endif /*_AICWF_SDMMC_H_*/

View File

@@ -0,0 +1,463 @@
/**
* aicwf_bus.c
*
* bus function declarations
*
* Copyright (C) AICSemi 2018-2020
*/
#include <linux/kthread.h>
#include <linux/netdevice.h>
#include <linux/printk.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/completion.h>
#include <linux/semaphore.h>
#include <linux/debugfs.h>
#include <linux/atomic.h>
#include <linux/vmalloc.h>
#include "aicsdio_txrxif.h"
#include "aic_bsp_driver.h"
int aicwf_bus_init(uint bus_hdrlen, struct device *dev)
{
int ret = 0;
struct aicwf_bus *bus_if;
if (!dev) {
txrx_err("device not found\n");
return -1;
}
bus_if = dev_get_drvdata(dev);
bus_if->cmd_buf = kzalloc(CMD_BUF_MAX, GFP_KERNEL);
if (!bus_if->cmd_buf) {
ret = -ENOMEM;
txrx_err("proto_attach failed\n");
goto fail;
}
memset(bus_if->cmd_buf, '\0', CMD_BUF_MAX);
init_completion(&bus_if->bustx_trgg);
init_completion(&bus_if->busrx_trgg);
#ifdef AICWF_SDIO_SUPPORT
bus_if->bustx_thread = kthread_run(aicwf_sdio_bustx_thread, (void *)bus_if, "aicwf_bustx_thread");
bus_if->busrx_thread = kthread_run(aicwf_sdio_busrx_thread, (void *)bus_if->bus_priv.sdio->rx_priv, "aicwf_busrx_thread");
#endif
if (IS_ERR(bus_if->bustx_thread)) {
bus_if->bustx_thread = NULL;
txrx_err("aicwf_bustx_thread run fail\n");
goto fail;
}
if (IS_ERR(bus_if->busrx_thread)) {
bus_if->busrx_thread = NULL;
txrx_err("aicwf_bustx_thread run fail\n");
goto fail;
}
return ret;
fail:
aicwf_bus_deinit(dev);
return ret;
}
void aicwf_bus_deinit(struct device *dev)
{
struct aicwf_bus *bus_if;
struct aic_sdio_dev *sdiodev;
if (!dev) {
txrx_err("device not found\n");
return;
}
sdio_dbg("%s", __func__);
bus_if = aicbsp_get_drvdata(dev);
aicwf_bus_stop(bus_if);
sdiodev = bus_if->bus_priv.sdio;
if (bus_if->cmd_buf) {
kfree(bus_if->cmd_buf);
bus_if->cmd_buf = NULL;
}
if (bus_if->bustx_thread) {
complete_all(&bus_if->bustx_trgg);
kthread_stop(bus_if->bustx_thread);
bus_if->bustx_thread = NULL;
}
}
void aicwf_frame_tx(void *dev, struct sk_buff *skb)
{
struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev;
aicwf_bus_txdata(sdiodev->bus_if, skb);
}
struct aicwf_tx_priv *aicwf_tx_init(void *arg)
{
struct aicwf_tx_priv *tx_priv;
tx_priv = kzalloc(sizeof(struct aicwf_tx_priv), GFP_KERNEL);
if (!tx_priv)
return NULL;
tx_priv->sdiodev = (struct aic_sdio_dev *)arg;
atomic_set(&tx_priv->aggr_count, 0);
tx_priv->aggr_buf = dev_alloc_skb(MAX_AGGR_TXPKT_LEN);
if (!tx_priv->aggr_buf) {
txrx_err("Alloc bus->txdata_buf failed!\n");
kfree(tx_priv);
return NULL;
}
tx_priv->head = tx_priv->aggr_buf->data;
tx_priv->tail = tx_priv->aggr_buf->data;
return tx_priv;
}
void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv)
{
if (tx_priv && tx_priv->aggr_buf)
dev_kfree_skb(tx_priv->aggr_buf);
kfree(tx_priv);
//tx_priv = NULL;
}
static bool aicwf_another_ptk(struct sk_buff *skb)
{
u8 *data;
u16 aggr_len = 0;
if (skb->data == NULL || skb->len == 0) {
return false;
}
data = skb->data;
aggr_len = (*skb->data | (*(skb->data + 1) << 8));
if (aggr_len == 0) {
return false;
}
return true;
}
int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
{
int ret = 0;
unsigned long flags = 0;
struct sk_buff *skb = NULL;
u16 pkt_len = 0;
struct sk_buff *skb_inblock = NULL;
u16 aggr_len = 0, adjust_len = 0;
u8 *data = NULL;
while (1) {
spin_lock_irqsave(&rx_priv->rxqlock, flags);
if (aicwf_is_framequeue_empty(&rx_priv->rxq)) {
spin_unlock_irqrestore(&rx_priv->rxqlock, flags);
break;
}
skb = aicwf_frame_dequeue(&rx_priv->rxq);
spin_unlock_irqrestore(&rx_priv->rxqlock, flags);
if (skb == NULL) {
txrx_err("skb_error\r\n");
break;
}
while (aicwf_another_ptk(skb)) {
data = skb->data;
pkt_len = (*skb->data | (*(skb->data + 1) << 8));
if ((skb->data[2] & SDIO_TYPE_CFG) != SDIO_TYPE_CFG) { // type : data
aggr_len = pkt_len + RX_HWHRD_LEN;
if (aggr_len & (RX_ALIGNMENT - 1))
adjust_len = roundup(aggr_len, RX_ALIGNMENT);
else
adjust_len = aggr_len;
skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL);//8 is for ccmp mic or wep icv
if (skb_inblock == NULL) {
txrx_err("no more space!\n");
aicwf_dev_skb_free(skb);
return -EBADE;
}
skb_put(skb_inblock, aggr_len);
memcpy(skb_inblock->data, data, aggr_len);
#if 0
rwnx_rxdataind_aicwf(rx_priv->sdiodev->rwnx_hw, skb_inblock, (void *)rx_priv);
#endif
skb_pull(skb, adjust_len);
} else { // type : config
aggr_len = pkt_len;
if (aggr_len & (RX_ALIGNMENT - 1))
adjust_len = roundup(aggr_len, RX_ALIGNMENT);
else
adjust_len = aggr_len;
skb_inblock = __dev_alloc_skb(aggr_len+4, GFP_KERNEL);
if (skb_inblock == NULL) {
txrx_err("no more space!\n");
aicwf_dev_skb_free(skb);
return -EBADE;
}
skb_put(skb_inblock, aggr_len+4);
memcpy(skb_inblock->data, data, aggr_len+4);
if ((*(skb_inblock->data + 2) & 0x7f) == SDIO_TYPE_CFG_CMD_RSP)
rwnx_rx_handle_msg(rx_priv->sdiodev, (struct ipc_e2a_msg *)(skb_inblock->data + 4));
#if 0
if ((*(skb_inblock->data + 2) & 0x7f) == SDIO_TYPE_CFG_DATA_CFM)
aicwf_sdio_host_tx_cfm_handler(&(rx_priv->sdiodev->rwnx_hw->sdio_env), (u32 *)(skb_inblock->data + 4));
#endif
skb_pull(skb, adjust_len+4);
}
}
/* skb_inblock no used currently, just free it! */
dev_kfree_skb(skb_inblock);
dev_kfree_skb(skb);
atomic_dec(&rx_priv->rx_cnt);
}
#if defined(CONFIG_SDIO_PWRCTRL)
aicwf_sdio_pwr_stctl(rx_priv->sdiodev, SDIO_ACTIVE_ST);
#endif
return ret;
}
static struct recv_msdu *aicwf_rxframe_queue_init(struct list_head *q, int qsize)
{
int i;
struct recv_msdu *req, *reqs;
reqs = vmalloc(qsize*sizeof(struct recv_msdu));
if (reqs == NULL)
return NULL;
req = reqs;
for (i = 0; i < qsize; i++) {
INIT_LIST_HEAD(&req->rxframe_list);
list_add(&req->rxframe_list, q);
req->len = 0;
req++;
}
return reqs;
}
struct aicwf_rx_priv *aicwf_rx_init(void *arg)
{
struct aicwf_rx_priv *rx_priv;
rx_priv = kzalloc(sizeof(struct aicwf_rx_priv), GFP_KERNEL);
if (!rx_priv)
return NULL;
rx_priv->sdiodev = (struct aic_sdio_dev *)arg;
aicwf_frame_queue_init(&rx_priv->rxq, 1, MAX_RXQLEN);
spin_lock_init(&rx_priv->rxqlock);
atomic_set(&rx_priv->rx_cnt, 0);
INIT_LIST_HEAD(&rx_priv->rxframes_freequeue);
spin_lock_init(&rx_priv->freeq_lock);
rx_priv->recv_frames = aicwf_rxframe_queue_init(&rx_priv->rxframes_freequeue, MAX_REORD_RXFRAME);
if (!rx_priv->recv_frames) {
txrx_err("no enough buffer for free recv frame queue!\n");
kfree(rx_priv);
return NULL;
}
spin_lock_init(&rx_priv->stas_reord_lock);
INIT_LIST_HEAD(&rx_priv->stas_reord_list);
return rx_priv;
}
static void aicwf_recvframe_queue_deinit(struct list_head *q)
{
struct recv_msdu *req, *next;
list_for_each_entry_safe(req, next, q, rxframe_list) {
list_del_init(&req->rxframe_list);
}
}
void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv)
{
if (rx_priv->sdiodev->bus_if->busrx_thread) {
complete_all(&rx_priv->sdiodev->bus_if->busrx_trgg);
kthread_stop(rx_priv->sdiodev->bus_if->busrx_thread);
rx_priv->sdiodev->bus_if->busrx_thread = NULL;
}
aicwf_frame_queue_flush(&rx_priv->rxq);
aicwf_recvframe_queue_deinit(&rx_priv->rxframes_freequeue);
if (rx_priv->recv_frames)
vfree(rx_priv->recv_frames);
kfree(rx_priv);
//rx_priv = NULL;
}
bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt)
{
return aicwf_frame_enq(dev, q, pkt, 0);
}
void aicwf_dev_skb_free(struct sk_buff *skb)
{
if (!skb)
return;
dev_kfree_skb_any(skb);
}
static struct sk_buff *aicwf_frame_queue_penq(struct frame_queue *pq, int prio, struct sk_buff *p)
{
struct sk_buff_head *q;
if (pq->queuelist[prio].qlen >= pq->qmax)
return NULL;
q = &pq->queuelist[prio];
__skb_queue_tail(q, p);
pq->qcnt++;
if (pq->hi_prio < prio)
pq->hi_prio = (u16)prio;
return p;
}
void aicwf_frame_queue_flush(struct frame_queue *pq)
{
int prio;
struct sk_buff_head *q;
struct sk_buff *p, *next;
for (prio = 0; prio < pq->num_prio; prio++) {
q = &pq->queuelist[prio];
skb_queue_walk_safe(q, p, next) {
skb_unlink(p, q);
aicwf_dev_skb_free(p);
pq->qcnt--;
}
}
}
void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len)
{
int prio;
memset(pq, 0, offsetof(struct frame_queue, queuelist) + (sizeof(struct sk_buff_head) * num_prio));
pq->num_prio = (u16)num_prio;
pq->qmax = (u16)max_len;
for (prio = 0; prio < num_prio; prio++) {
skb_queue_head_init(&pq->queuelist[prio]);
}
}
struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out)
{
int prio;
if (pq->qcnt == 0)
return NULL;
for (prio = 0; prio < pq->hi_prio; prio++)
if (!skb_queue_empty(&pq->queuelist[prio]))
break;
if (prio_out)
*prio_out = prio;
return skb_peek_tail(&pq->queuelist[prio]);
}
bool aicwf_is_framequeue_empty(struct frame_queue *pq)
{
int prio, len = 0;
for (prio = 0; prio <= pq->hi_prio; prio++)
len += pq->queuelist[prio].qlen;
if (len > 0)
return false;
else
return true;
}
struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq)
{
struct sk_buff_head *q;
struct sk_buff *p;
int prio;
if (pq->qcnt == 0)
return NULL;
while ((prio = pq->hi_prio) > 0 && skb_queue_empty(&pq->queuelist[prio]))
pq->hi_prio--;
q = &pq->queuelist[prio];
p = __skb_dequeue(q);
if (p == NULL)
return NULL;
pq->qcnt--;
return p;
}
static struct sk_buff *aicwf_skb_dequeue_tail(struct frame_queue *pq, int prio)
{
struct sk_buff_head *q = &pq->queuelist[prio];
struct sk_buff *p = skb_dequeue_tail(q);
if (!p)
return NULL;
pq->qcnt--;
return p;
}
bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio)
{
struct sk_buff *p = NULL;
int prio_modified = -1;
if (q->queuelist[prio].qlen < q->qmax && q->qcnt < q->qmax) {
aicwf_frame_queue_penq(q, prio, pkt);
return true;
}
if (q->queuelist[prio].qlen >= q->qmax) {
prio_modified = prio;
} else if (q->qcnt >= q->qmax) {
p = aicwf_frame_queue_peek_tail(q, &prio_modified);
if (prio_modified > prio)
return false;
}
if (prio_modified >= 0) {
if (prio_modified == prio)
return false;
p = aicwf_skb_dequeue_tail(q, prio_modified);
aicwf_dev_skb_free(p);
p = aicwf_frame_queue_penq(q, prio_modified, pkt);
if (p == NULL)
txrx_err("failed\n");
}
return p != NULL;
}

View File

@@ -0,0 +1,214 @@
/**
* aicwf_txrxif.h
*
* bus function declarations
*
* Copyright (C) AICSemi 2018-2020
*/
#ifndef _AICWF_TXRXIF_H_
#define _AICWF_TXRXIF_H_
#include <linux/skbuff.h>
#include <linux/sched.h>
#include "aicsdio.h"
#define CMD_BUF_MAX 1536
#define TXPKT_BLOCKSIZE 512
#define MAX_AGGR_TXPKT_LEN (1536*4)
#define CMD_TX_TIMEOUT 5000
#define TX_ALIGNMENT 4
#define RX_HWHRD_LEN 60 //58->60 word allined
#define CCMP_OR_WEP_INFO 8
#define MAX_RXQLEN 2000
#define RX_ALIGNMENT 4
#define DEBUG_ERROR_LEVEL 0
#define DEBUG_DEBUG_LEVEL 1
#define DEBUG_INFO_LEVEL 2
#define DBG_LEVEL DEBUG_DEBUG_LEVEL
#define txrx_err(fmt, ...) pr_err("aicbsp: txrx_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__)
#define sdio_err(fmt, ...) pr_err("aicbsp: sdio_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__)
#define usb_err(fmt, ...) pr_err("aicbsp: usb_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__)
#if DBG_LEVEL >= DEBUG_DEBUG_LEVEL
#define sdio_dbg(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__)
#define usb_dbg(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__)
#else
#define sdio_dbg(fmt, ...)
#define usb_dbg(fmt, ...)
#endif
#if DBG_LEVEL >= DEBUG_INFO_LEVEL
#define sdio_info(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__)
#define usb_info(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__)
#else
#define sdio_info(fmt, ...)
#define usb_info(fmt, ...)
#endif
enum aicwf_bus_state {
BUS_DOWN_ST,
BUS_UP_ST
};
struct aicwf_bus_ops {
int (*start) (struct device *dev);
void (*stop) (struct device *dev);
int (*txdata) (struct device *dev, struct sk_buff *skb);
int (*txmsg) (struct device *dev, u8 *msg, uint len);
};
struct frame_queue {
u16 num_prio;
u16 hi_prio;
u16 qmax; /* max number of queued frames */
u16 qcnt;
struct sk_buff_head queuelist[8];
};
struct aicwf_bus {
union {
struct aic_sdio_dev *sdio;
struct aic_usb_dev *usb;
} bus_priv;
struct device *dev;
struct aicwf_bus_ops *ops;
enum aicwf_bus_state state;
u8 *cmd_buf;
struct completion bustx_trgg;
struct completion busrx_trgg;
struct task_struct *bustx_thread;
struct task_struct *busrx_thread;
};
struct aicwf_tx_priv {
#ifdef AICWF_SDIO_SUPPORT
struct aic_sdio_dev *sdiodev;
int fw_avail_bufcnt;
//for cmd tx
u8 *cmd_buf;
uint cmd_len;
bool cmd_txstate;
bool cmd_tx_succ;
struct semaphore cmd_txsema;
wait_queue_head_t cmd_txdone_wait;
//for data tx
atomic_t tx_pktcnt;
struct frame_queue txq;
spinlock_t txqlock;
struct semaphore txctl_sema;
#endif
#ifdef AICWF_USB_SUPPORT
struct aic_usb_dev *usbdev;
#endif
struct sk_buff *aggr_buf;
atomic_t aggr_count;
u8 *head;
u8 *tail;
};
#define MAX_REORD_RXFRAME 250
#define REORDER_UPDATE_TIME 50
#define AICWF_REORDER_WINSIZE 64
#define SN_LESS(a, b) (((a-b)&0x800) != 0)
#define SN_EQUAL(a, b) (a == b)
struct reord_ctrl {
struct aicwf_rx_priv *rx_priv;
u8 enable;
u16 ind_sn;
u8 wsize_b;
spinlock_t reord_list_lock;
struct list_head reord_list;
struct timer_list reord_timer;
struct work_struct reord_timer_work;
};
struct reord_ctrl_info {
u8 mac_addr[6];
struct reord_ctrl preorder_ctrl[8];
struct list_head list;
};
struct recv_msdu {
struct sk_buff *pkt;
u8 tid;
u16 seq_num;
uint len;
u8 *rx_data;
//for pending rx reorder list
struct list_head reord_pending_list;
//for total frame list, when rxframe from busif, dequeue, when submit frame to net, enqueue
struct list_head rxframe_list;
struct reord_ctrl *preorder_ctrl;
};
struct aicwf_rx_priv {
struct aic_sdio_dev *sdiodev;
void *rwnx_vif;
atomic_t rx_cnt;
u32 data_len;
spinlock_t rxqlock;
struct frame_queue rxq;
spinlock_t freeq_lock;
struct list_head rxframes_freequeue;
struct list_head stas_reord_list;
spinlock_t stas_reord_lock;
struct recv_msdu *recv_frames;
};
static inline int aicwf_bus_start(struct aicwf_bus *bus)
{
return bus->ops->start(bus->dev);
}
static inline void aicwf_bus_stop(struct aicwf_bus *bus)
{
bus->ops->stop(bus->dev);
}
static inline int aicwf_bus_txdata(struct aicwf_bus *bus, struct sk_buff *skb)
{
return bus->ops->txdata(bus->dev, skb);
}
static inline int aicwf_bus_txmsg(struct aicwf_bus *bus, u8 *msg, uint len)
{
return bus->ops->txmsg(bus->dev, msg, len);
}
static inline void aicwf_sched_timeout(u32 millisec)
{
ulong timeout = 0, expires = 0;
expires = jiffies + msecs_to_jiffies(millisec);
timeout = millisec;
while (timeout) {
timeout = schedule_timeout(timeout);
if (time_after(jiffies, expires))
break;
}
}
int aicwf_bus_init(uint bus_hdrlen, struct device *dev);
void aicwf_bus_deinit(struct device *dev);
void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv);
void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv);
struct aicwf_tx_priv *aicwf_tx_init(void *arg);
struct aicwf_rx_priv *aicwf_rx_init(void *arg);
void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len);
void aicwf_frame_queue_flush(struct frame_queue *pq);
bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio);
bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt);
bool aicwf_is_framequeue_empty(struct frame_queue *pq);
void aicwf_frame_tx(void *dev, struct sk_buff *skb);
void aicwf_dev_skb_free(struct sk_buff *skb);
struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq);
struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out);
#endif /* _AICWF_TXRXIF_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
int aicwf_get_firmware_array(char* fw_name, u32 **fw_buf);

View File

@@ -0,0 +1,62 @@
#include <linux/slab.h>
#include "aicsdio_txrxif.h"
#include "aic_bsp_driver.h"
struct prealloc_txq{
int prealloced;
void *txq;
size_t size;
};
struct prealloc_txq prealloc_txq;
#define MAX_TXQ_SIZE 30 * 1024
void *aicwf_prealloc_txq_alloc(size_t size)
{
BUG_ON(size > MAX_TXQ_SIZE);
//check prealloc_txq.size
if((int)prealloc_txq.size != (int)size)
{
AICWFDBG(LOGINFO, "%s size is diff will to be kzalloc \r\n", __func__);
if(prealloc_txq.txq != NULL)
{
AICWFDBG(LOGINFO, "%s txq to kfree \r\n", __func__);
kfree(prealloc_txq.txq);
prealloc_txq.txq = NULL;
}
prealloc_txq.size = size;
prealloc_txq.prealloced = 0;
}
//check prealloc or not
if(!prealloc_txq.prealloced)
{
prealloc_txq.txq = kzalloc(size, GFP_KERNEL);
if(!prealloc_txq.txq){
AICWFDBG(LOGERROR, "%s txq kzalloc fail \r\n", __func__);
}else{
AICWFDBG(LOGINFO, "%s txq kzalloc successful \r\n", __func__);
prealloc_txq.prealloced = 1;
}
}else{
AICWFDBG(LOGINFO, "%s txq not need to kzalloc \r\n", __func__);
}
return prealloc_txq.txq;
}
void aicwf_prealloc_txq_free(void)
{
if(prealloc_txq.txq != NULL)
{
AICWFDBG(LOGINFO, "%s txq to kfree \r\n", __func__);
kfree(prealloc_txq.txq);
prealloc_txq.txq = NULL;
}
}
EXPORT_SYMBOL(aicwf_prealloc_txq_alloc);

View File

@@ -0,0 +1,4 @@
void aicwf_prealloc_txq_free(void);

View File

@@ -0,0 +1,161 @@
#include <linux/memory.h>
#include "md5.h"
unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
void MD5Init(MD5_CTX *context)
{
context->count[0] = 0;
context->count[1] = 0;
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
}
void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen)
{
unsigned int i = 0,index = 0,partlen = 0;
index = (context->count[0] >> 3) & 0x3F;
partlen = 64 - index;
context->count[0] += inputlen << 3;
if(context->count[0] < (inputlen << 3))
context->count[1]++;
context->count[1] += inputlen >> 29;
if(inputlen >= partlen)
{
memcpy(&context->buffer[index],input,partlen);
MD5Transform(context->state,context->buffer);
for(i = partlen;i+64 <= inputlen;i+=64)
MD5Transform(context->state,&input[i]);
index = 0;
}
else
{
i = 0;
}
memcpy(&context->buffer[index],&input[i],inputlen-i);
}
void MD5Final(MD5_CTX *context,unsigned char digest[16])
{
unsigned int index = 0,padlen = 0;
unsigned char bits[8];
index = (context->count[0] >> 3) & 0x3F;
padlen = (index < 56)?(56-index):(120-index);
MD5Encode(bits,context->count,8);
MD5Update(context,PADDING,padlen);
MD5Update(context,bits,8);
MD5Encode(digest,context->state,16);
}
void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len)
{
unsigned int i = 0,j = 0;
while(j < len)
{
output[j] = input[i] & 0xFF;
output[j+1] = (input[i] >> 8) & 0xFF;
output[j+2] = (input[i] >> 16) & 0xFF;
output[j+3] = (input[i] >> 24) & 0xFF;
i++;
j+=4;
}
}
void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len)
{
unsigned int i = 0,j = 0;
while(j < len)
{
output[i] = (input[j]) |
(input[j+1] << 8) |
(input[j+2] << 16) |
(input[j+3] << 24);
i++;
j+=4;
}
}
void MD5Transform(unsigned int state[4],unsigned char block[64])
{
unsigned int a = state[0];
unsigned int b = state[1];
unsigned int c = state[2];
unsigned int d = state[3];
unsigned int x[64];
MD5Decode(x,block,64);
FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */
FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */
FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */
FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */
FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */
/* Round 2 */
GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */
HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */
/* Round 4 */
II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */
II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */
II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */
II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */
II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */
II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */
II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
}

View File

@@ -0,0 +1,48 @@
#ifndef MD5_H
#define MD5_H
typedef struct
{
unsigned int count[2];
unsigned int state[4];
unsigned char buffer[64];
}MD5_CTX;
#define F(x,y,z) ((x & y) | (~x & z))
#define G(x,y,z) ((x & z) | (y & ~z))
#define H(x,y,z) (x^y^z)
#define I(x,y,z) (y ^ (x | ~z))
#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))
#define FF(a,b,c,d,x,s,ac) \
{ \
a += F(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
#define GG(a,b,c,d,x,s,ac) \
{ \
a += G(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
#define HH(a,b,c,d,x,s,ac) \
{ \
a += H(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
#define II(a,b,c,d,x,s,ac) \
{ \
a += I(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
void MD5Init(MD5_CTX *context);
void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen);
void MD5Final(MD5_CTX *context,unsigned char digest[16]);
void MD5Transform(unsigned int state[4],unsigned char block[64]);
void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len);
void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len);
#endif

View File

@@ -0,0 +1,4 @@
#define RWNX_VERS_REV "241c091M (master)"
#define RWNX_VERS_MOD "6.4.3.0"
#define RWNX_VERS_BANNER "rwnx v6.4.3.0 - - 241c091M (master)"
#define RELEASE_DATE "2023_0904_1726"

View File

@@ -0,0 +1,5 @@
config AIC8800_BTLPM_SUPPORT
tristate "AIC8800 bluetooth Support"
help
This is support for aic bluetooh driver.

View File

@@ -0,0 +1,80 @@
CONFIG_AIC8800_BTLPM_SUPPORT = m
obj-$(CONFIG_AIC8800_BTLPM_SUPPORT) := aic8800_btlpm.o
ccflags-y += -I$(srctree)/$(src)/../aic8800_bsp
aic8800_btlpm-y := \
aic_bluetooth_main.o \
rfkill.o \
lpm.o
# Platform support list
CONFIG_PLATFORM_ROCKCHIP ?= n
CONFIG_PLATFORM_ALLWINNER ?= n
CONFIG_PLATFORM_AMLOGIC ?= n
CONFIG_PLATFORM_UBUNTU ?= y
ccflags-y += -DAIC_TRACE_INCLUDE_PATH=$(src)
ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y)
KDIR ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/kernel
ARCH ?= arm
CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
#KDIR ?= /home/yaya/E/Rockchip/3229/Android10/SDK/kernel/
#ARCH ?= arm
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android10/SDK/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
#KDIR ?= /home/yaya/E/Rockchip/3288/Android10/kernel/kernel/
#ARCH ?= arm
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3288/Android10/tool/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux#-gnueabihf-
#KDIR ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/kernel
#ARCH ?= arm
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
#KDIR ?= /home/yaya/E/Rockchip/3328/Android9/SDK/SDK/kernel
#ARCH ?= arm64
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3328/Android9/SDK/SDK/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP
ccflags-y += -DANDROID_PLATFORM
endif
ifeq ($(CONFIG_PLATFORM_ALLWINNER), y)
ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER
KDIR ?= /home/yaya/E/Allwinner/R818/R818/AndroidQ/lichee/kernel/linux-4.9/
ARCH ?= arm64
CROSS_COMPILE ?= /home/yaya/E/Allwinner/R818/R818/AndroidQ/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-
ccflags-y += -DANDROID_PLATFORM
endif
ifeq ($(CONFIG_PLATFORM_AMLOGIC), y)
ccflags-$(CONFIG_PLATFORM_NANOPI) += -DCONFIG_PLATFORM_NANOPI
ccflags-y += -DANDROID_PLATFORM
endif
ifeq ($(CONFIG_PLATFORM_UBUNTU), y)
KDIR ?= /lib/modules/$(shell uname -r)/build
PWD ?= $(shell pwd)
KVER ?= $(shell uname -r)
MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/
ARCH ?= x86_64
CROSS_COMPILE ?=
endif
all: modules
modules:
make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
install:
mkdir -p $(MODDESTDIR)
install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR)
/sbin/depmod -a ${KVER}
uninstall:
rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko
/sbin/depmod -a ${KVER}
clean:
rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,84 @@
#include <linux/module.h>
#include <linux/inetdevice.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/platform_device.h>
//#include "lpm.h"
#include "rfkill.h"
#define DRV_CONFIG_FW_NAME "fw.bin"
#define DRV_DESCRIPTION "AIC BLUETOOTH"
#define DRV_COPYRIGHT "Copyright(c) 2015-2020 AICSemi"
#define DRV_AUTHOR "AICSemi"
#define DRV_VERS_MOD "1.0"
static struct platform_device *aicbt_pdev;
static struct platform_driver aicbt_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "aic_bt",
},
//.probe = aicbt_probe,
//.remove = aicbt_remove,
};
static int __init aic_bluetooth_mod_init(void)
{
int ret;
printk("%s\n", __func__);
ret = platform_driver_register(&aicbt_driver);
if (ret) {
pr_err("register platform driver failed: %d\n", ret);
return ret;
}
aicbt_pdev = platform_device_alloc("aic-bt", -1);
ret = platform_device_add(aicbt_pdev);
if (ret) {
pr_err("register platform device failed: %d\n", ret);
goto err0;
}
ret = rfkill_bluetooth_init(aicbt_pdev);
if (ret) {
pr_err("rfkill init fail\n");
goto err1;
}
#if 0
ret = bluesleep_init(aicbt_pdev);
if (ret) {
pr_err("bluesleep init fail\n");
goto err2;
}
#endif
return 0;
//err2:
rfkill_bluetooth_remove(aicbt_pdev);
err1:
platform_device_del(aicbt_pdev);
err0:
platform_driver_unregister(&aicbt_driver);
return ret;
}
static void __exit aic_bluetooth_mod_exit(void)
{
printk("%s\n", __func__);
//bluesleep_exit(aicbt_pdev);
rfkill_bluetooth_remove(aicbt_pdev);
platform_device_del(aicbt_pdev);
platform_driver_unregister(&aicbt_driver);
}
module_init(aic_bluetooth_mod_init);
module_exit(aic_bluetooth_mod_exit);
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERS_MOD);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,18 @@
#ifndef __AIC_BSP_EXPORT_H
#define __AIC_BSP_EXPORT_H
#define AIC_BLUETOOTH 0
#define AIC_WIFI 1
#define AIC_PWR_OFF 0
#define AIC_PWR_ON 1
struct aicbsp_feature_t {
bool band_5g_support;
uint32_t sdio_clock;
uint8_t sdio_phase;
};
int aicbsp_set_subsys(int, int);
int aicbsp_get_feature(struct aicbsp_feature_t *feature);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
/*
* Copyright (C) 2015 Spreadtrum Communications Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __LPM_H
#define __LPM_H
int bluesleep_init(struct platform_device *pdev);
int bluesleep_exit(struct platform_device *dev);
#endif

View File

@@ -0,0 +1,81 @@
/*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/rfkill.h>
#include <linux/gpio.h>
#include <linux/ioport.h>
#include <linux/clk.h>
#include <linux/of_gpio.h>
#include <linux/version.h>
#include "aic_bsp_export.h"
static struct rfkill *bt_rfk;
static const char bt_name[] = "bluetooth";
static int bluetooth_set_power(void *data, bool blocked)
{
pr_info("%s: start_block=%d\n", __func__, blocked);
if (!blocked) {
aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_ON);
} else {
aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_OFF);
}
pr_info("%s: end_block=%d\n", __func__, blocked);
return 0;
}
static struct rfkill_ops rfkill_bluetooth_ops = {
.set_block = bluetooth_set_power,
};
int rfkill_bluetooth_init(struct platform_device *pdev)
{
int rc = 0;
pr_info("-->%s\n", __func__);
bt_rfk = rfkill_alloc(bt_name, &pdev->dev, RFKILL_TYPE_BLUETOOTH,
&rfkill_bluetooth_ops, NULL);
if (!bt_rfk) {
rc = -ENOMEM;
goto err_rfkill_alloc;
}
/* userspace cannot take exclusive control */
rfkill_init_sw_state(bt_rfk, true);
rc = rfkill_register(bt_rfk);
if (rc)
goto err_rfkill_reg;
pr_info("<--%s\n", __func__);
return 0;
err_rfkill_reg:
rfkill_destroy(bt_rfk);
err_rfkill_alloc:
return rc;
}
int rfkill_bluetooth_remove(struct platform_device *dev)
{
pr_info("-->%s\n", __func__);
rfkill_unregister(bt_rfk);
rfkill_destroy(bt_rfk);
pr_info("<--%s\n", __func__);
return 0;
}

View File

@@ -0,0 +1,17 @@
/*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __RFKILL_H__
#define __RFKILL_H__
int rfkill_bluetooth_init(struct platform_device *pdev);
int rfkill_bluetooth_remove(struct platform_device *pdev);
#endif

View File

@@ -0,0 +1,5 @@
config AIC8800_WLAN_SUPPORT
tristate "AIC8800 wlan Support"
help
This is support for aic wifi driver.

View File

@@ -0,0 +1,355 @@
RWNX_VERS_NUM := 6.4.3.0
CONFIG_COUNTRY_CODE = "00"
MODULE_NAME = aic8800_fdrv
# Support of bootrom start
CONFIG_START_FROM_BOOTROM = y
# Support of pmic setting, new version bootrom avaliable
CONFIG_PMIC_SETTING ?=y
# Select 8800DC/DW DCDC_VRF mode, check your board
CONFIG_VRF_DCDC_MODE = y
# ROM patch enabled option
CONFIG_ROM_PATCH_EN ?=y
# Support chip with mcu
CONFIG_MCU_INTEGRATED ?= n
CONFIG_MCU_MESSAGE ?= n
ifeq ($(CONFIG_MCU_INTEGRATED), y)
CONFIG_PMIC_SETTING = n
else
CONFIG_MCU_MESSAGE ?= n
endif
#
# WAITING FOR KCONFIG {
#
CONFIG_RWNX_FULLMAC ?= y
CONFIG_RWNX_FHOST ?= n
#
# DEBUG OPTIONS
CONFIG_RWNX_UM_HELPER_DFLT ?= "/dini/dini_bin/rwnx_umh.sh"
#
# FW ARCH:
CONFIG_RWNX_SDM ?= n
CONFIG_RWNX_TL4 ?= n
# IPC version
CONFIG_RWNX_OLD_IPC ?= n
# Support of P2P DebugFS for enabling/disabling NoA and OppPS
CONFIG_RWNX_P2P_DEBUGFS := n
#
# } // WAITING FOR KCONFIG
#
# Enable A-MSDU support (need FW support)
## Select this if FW is compiled with AMSDU support
CONFIG_RWNX_SPLIT_TX_BUF ?= n
## Select this TO send AMSDU
CONFIG_RWNX_AMSDUS_TX ?= n
# Enable BFMER support (need FW support)
CONFIG_RWNX_BFMER ?= n
CONFIG_SDIO_SUPPORT =y
CONFIG_USB_SUPPORT =n
CONFIG_RX_REORDER ?=y
CONFIG_ARP_OFFLOAD =y
CONFIG_RADAR_OR_IR_DETECT =n
CONFIG_DOWNLOAD_FW =n
CONFIG_RFTEST=y
CONFIG_USB_BT =y
CONFIG_USE_5G ?= y
CONFIG_SDIO_PWRCTRL ?= y
CONFIG_CREATE_TRACE_POINTS = n
CONFIG_TXRX_THREAD_PRIO = n
# CONFIG_COEX = n for BT_ONLY, CONFIG_COEX =y for combo and sw
CONFIG_COEX = y
CONFIG_RX_NETIF_RECV_SKB = y
CONFIG_GPIO_WAKEUP = n
CONFIG_SET_VENDOR_EXTENSION_IE = n
CONFIG_SUPPORT_REALTIME_CHANGE_MAC = y
CONFIG_WPA3_FOR_OLD_KERNEL ?= n
CONFIG_VHT_FOR_OLD_KERNEL ?= n
CONFIG_HE_FOR_OLD_KERNEL ?= n
CONFIG_PREALLOC_RX_SKB = n
CONFIG_WIFI_SUSPEND_FOR_LINUX = n
# Need to set fw path in BOARD_KERNEL_CMDLINE
CONFIG_USE_FW_REQUEST = n
CONFIG_USE_P2P0=n
CONFIG_BR_SUPPORT =n
BR_NAME = br0
CONFIG_FDRV_NO_REG_SDIO=n
CONFIG_SCHED_SCAN = y
CONFIG_OOB = n
CONFIG_USE_CUSTOMER_MAC = n
CONFIG_PREALLOC_TXQ = y
CONFIG_DPD = n
CONFIG_FORCE_DPD_CALIB = n
# Support of MU-MIMO transmission (need FW support)
ifeq ($(CONFIG_RWNX_BFMER), y)
CONFIG_RWNX_MUMIMO_TX ?= n
else
CONFIG_RWNX_MUMIMO_TX = n
endif
# Enable handling of radar event
CONFIG_RWNX_RADAR ?= y
# Enable HW queue for Broadcast/Multicast traffic (need FW support)
CONFIG_RWNX_BCMC ?= y
# Enable Monitor+Data interface support (need FW support)
CONFIG_RWNX_MON_DATA =y
# extra DEBUG config
CONFIG_RWNX_SW_PROFILING ?= n
CONFIG_RWNX_DBG ?= y
CONFIG_DEBUG_FS ?= n
obj-$(CONFIG_AIC8800_WLAN_SUPPORT) := $(MODULE_NAME).o
$(MODULE_NAME)-y := \
rwnx_gki.o \
rwnx_msg_tx.o \
rwnx_msg_rx.o \
rwnx_utils.o \
rwnx_cmds.o \
rwnx_irqs.o \
rwnx_cfgfile.o \
rwnx_strs.o \
rwnx_rx.o \
rwnx_tx.o \
rwnx_txq.o \
rwnx_main.o \
rwnx_mod_params.o \
rwnx_mesh.o \
rwnx_platform.o \
rwnx_pci.o \
rwnx_dini.o \
rwnx_v7.o \
ipc_host.o \
rwnx_tdls.o \
aic_vendor.o \
md5.o \
aicwf_compat_8800dc.o \
aicwf_compat_8800d80.o \
rwnx_wakelock.o \
regdb.o \
aicwf_rx_prealloc.o
$(MODULE_NAME)-$(CONFIG_BR_SUPPORT) += aic_br_ext.o
$(MODULE_NAME)-$(CONFIG_RWNX_RADAR) += rwnx_radar.o
$(MODULE_NAME)-$(CONFIG_DEBUG_FS) += rwnx_debugfs.o
$(MODULE_NAME)-$(CONFIG_DEBUG_FS) += rwnx_fw_trace.o
$(MODULE_NAME)-$(CONFIG_NL80211_TESTMODE) += rwnx_testmode.o
$(MODULE_NAME)-$(CONFIG_RWNX_BFMER) += rwnx_bfmer.o
$(MODULE_NAME)-$(CONFIG_RWNX_MUMIMO_TX) += rwnx_mu_group.o
$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += sdio_host.o
$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += aicwf_txrxif.o
$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += aicwf_sdio.o
$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += usb_host.o
$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += aicwf_txrxif.o
$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += aicwf_usb.o
ccflags-$(CONFIG_DEBUG_FS) += -DCONFIG_RWNX_DEBUGFS
ccflags-$(CONFIG_DEBUG_FS) += -DCONFIG_RWNX_UM_HELPER_DFLT=\"$(CONFIG_RWNX_UM_HELPER_DFLT)\"
ccflags-$(CONFIG_RWNX_P2P_DEBUGFS) += -DCONFIG_RWNX_P2P_DEBUGFS
# FW VARS
ccflags-y += -DNX_VIRT_DEV_MAX=4
#for 8800D and DCDW u01
#ccflags-y += -DNX_REMOTE_STA_MAX=10
#for 8800DCDW u02
ccflags-y += -DNX_REMOTE_STA_MAX_FOR_OLD_IC=10
ccflags-y += -DNX_REMOTE_STA_MAX=32
ccflags-y += -DNX_MU_GROUP_MAX=62
ccflags-y += -DNX_TXDESC_CNT=64
ccflags-y += -DNX_TX_MAX_RATES=4
ccflags-y += -DNX_CHAN_CTXT_CNT=3
# FW ARCH:
ccflags-$(CONFIG_RWNX_SDM) += -DCONFIG_RWNX_SDM
ccflags-$(CONFIG_RWNX_TL4) += -DCONFIG_RWNX_TL4
ccflags-$(CONFIG_RWNX_OLD_IPC) += -DCONFIG_RWNX_OLD_IPC
ccflags-$(CONFIG_PLATFORM_NANOPI_M4) += -DCONFIG_NANOPI_M4
ccflags-$(CONFIG_PLATFORM_INGENIC_T20) += -DCONFIG_INGENIC_T20
ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER
ccflags-$(CONFIG_START_FROM_BOOTROM) += -DCONFIG_START_FROM_BOOTROM
ccflags-$(CONFIG_PMIC_SETTING) += -DCONFIG_PMIC_SETTING
ccflags-$(CONFIG_VRF_DCDC_MODE) += -DCONFIG_VRF_DCDC_MODE
ccflags-$(CONFIG_ROM_PATCH_EN) += -DCONFIG_ROM_PATCH_EN
ccflags-$(CONFIG_HE_FOR_OLD_KERNEL) += -DCONFIG_HE_FOR_OLD_KERNEL
ccflags-$(CONFIG_MCU_INTEGRATED) += -DCONFIG_MCU_INTEGRATED
ccflags-$(CONFIG_MCU_MESSAGE) += -DCONFIG_MCU_MESSAGE
ccflags-$(CONFIG_COEX) += -DCONFIG_COEX
ccflags-y += -DCONFIG_RWNX_FULLMAC
ccflags-y += -I$(srctree)
ccflags-y += -I$(srctree)/$(src)
ccflags-y += -I$(srctree)/$(src)/../aic8800_bsp
ccflags-y += -DCONFIG_AIC_FW_PATH=\"$(CONFIG_AIC_FW_PATH)\"
ccflags-$(CONFIG_RWNX_RADAR) += -DCONFIG_RWNX_RADAR
ccflags-$(CONFIG_RWNX_MON_DATA) += -DCONFIG_RWNX_MON_DATA
ccflags-$(CONFIG_RWNX_BFMER) += -DCONFIG_RWNX_BFMER
ccflags-$(CONFIG_RWNX_SPLIT_TX_BUF) += -DCONFIG_RWNX_SPLIT_TX_BUF
ifeq ($(CONFIG_RWNX_SPLIT_TX_BUF), y)
ccflags-$(CONFIG_RWNX_AMSDUS_TX) += -DCONFIG_RWNX_AMSDUS_TX
endif
ccflags-$(CONFIG_RWNX_DBG) += -DCONFIG_RWNX_DBG
ccflags-$(CONFIG_RWNX_SW_PROFILING) += -DCONFIG_RWNX_SW_PROFILING
ccflags-$(CONFIG_RWNX_MUMIMO_TX) += -DCONFIG_RWNX_MUMIMO_TX
ccflags-$(CONFIG_RFTEST) += -DCONFIG_RFTEST
ccflags-y += -DDEFAULT_COUNTRY_CODE=""\$(CONFIG_COUNTRY_CODE)"\"
ccflags-$(CONFIG_USE_5G) += -DUSE_5G
ccflags-$(CONFIG_CREATE_TRACE_POINTS) += -DCREATE_TRACE_POINTS
ccflags-$(CONFIG_TXRX_THREAD_PRIO) += -DCONFIG_TXRX_THREAD_PRIO
ccflags-$(CONFIG_GPIO_WAKEUP) += -DCONFIG_GPIO_WAKEUP
ccflags-$(CONFIG_SET_VENDOR_EXTENSION_IE) += -DCONFIG_SET_VENDOR_EXTENSION_IE
ccflags-$(CONFIG_SUPPORT_REALTIME_CHANGE_MAC) += -DCONFIG_SUPPORT_REALTIME_CHANGE_MAC
ccflags-$(CONFIG_WPA3_FOR_OLD_KERNEL) += -DCONFIG_WPA3_FOR_OLD_KERNEL
ccflags-$(CONFIG_VHT_FOR_OLD_KERNEL) += -DCONFIG_VHT_FOR_OLD_KERNEL
ccflags-$(CONFIG_PREALLOC_RX_SKB) += -DCONFIG_PREALLOC_RX_SKB
ccflags-$(CONFIG_WIFI_SUSPEND_FOR_LINUX) += -DCONFIG_WIFI_SUSPEND_FOR_LINUX
ccflags-$(CONFIG_USE_FW_REQUEST) += -DCONFIG_USE_FW_REQUEST
ccflags-$(CONFIG_USE_P2P0) += -DCONFIG_USE_P2P0
ccflags-$(CONFIG_FDRV_NO_REG_SDIO) += -DCONFIG_FDRV_NO_REG_SDIO
ccflags-$(CONFIG_SCHED_SCAN) += -DCONFIG_SCHED_SCAN
ccflags-$(CONFIG_OOB) += -DCONFIG_OOB
ccflags-$(CONFIG_USE_CUSTOMER_MAC) += -DCONFIG_USE_CUSTOMER_MAC
ccflags-$(CONFIG_PREALLOC_TXQ) += -DCONFIG_PREALLOC_TXQ
ccflags-$(CONFIG_DPD) += -DCONFIG_DPD
ccflags-$(CONFIG_FORCE_DPD_CALIB) += -DCONFIG_FORCE_DPD_CALIB -DCONFIG_DPD
ifeq ($(CONFIG_SDIO_SUPPORT), y)
ccflags-y += -DAICWF_SDIO_SUPPORT
ccflags-$(CONFIG_SDIO_PWRCTRL) += -DCONFIG_SDIO_PWRCTRL
endif
ifeq ($(CONFIG_USB_SUPPORT), y)
ccflags-y += -DAICWF_USB_SUPPORT
endif
ifeq ($(CONFIG_BR_SUPPORT), y)
ccflags-y += -DCONFIG_BR_SUPPORT
ccflags-y += '-DCONFIG_BR_SUPPORT_BRNAME="'$(BR_NAME)'"'
endif
ifeq ($(CONFIG_RWNX_MUMIMO_TX), y)
ccflags-y += -DCONFIG_USER_MAX=2
else
ccflags-y += -DCONFIG_USER_MAX=1
endif
ifeq ($(CONFIG_RWNX_BCMC), y)
ccflags-y += -DNX_TXQ_CNT=5
else
ccflags-y += -DNX_TXQ_CNT=4
endif
# For old kernel (<=3.19)
ifeq ($(shell test $(VERSION) -lt 4 -a "$(CONFIG_VENDOR_RWNX)" = y ; echo $$?),0)
ccflags-y += -DCONFIG_VENDOR_RWNX_VHT_NO80
endif
ccflags-$(CONFIG_RX_REORDER) += -DAICWF_RX_REORDER
ccflags-$(CONFIG_ARP_OFFLOAD) += -DAICWF_ARP_OFFLOAD
ccflags-$(CONFIG_RADAR_DETECT) += -DRADAR_OR_IR_DETECT
ccflags-$(CONFIG_DOWNLOAD_FW) += -DCONFIG_DOWNLOAD_FW
ccflags-$(CONFIG_RX_NETIF_RECV_SKB) += -DCONFIG_RX_NETIF_RECV_SKB
# Platform support list
CONFIG_PLATFORM_ROCKCHIP ?= n
CONFIG_PLATFORM_ALLWINNER ?= n
CONFIG_PLATFORM_INGENIC_T20 ?= n
CONFIG_PLATFORM_AMLOGIC ?= n
CONFIG_PLATFORM_UBUNTU ?= y
ccflags-y += -DAIC_TRACE_INCLUDE_PATH=$(src)
ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y)
#KDIR ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/kernel
#ARCH ?= arm
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
#KDIR ?= /home/yaya/E/Rockchip/3399/rk3399-android-10/kernel
#ARCH ?= arm64
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3399/rk3399-android-10/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
#KDIR ?= /home/yaya/E/Rockchip/3288/Android10/kernel/kernel/
#ARCH ?= arm
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3288/Android10/tool/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
#KDIR ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/kernel
#ARCH ?= arm
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
#KDIR ?= /home/yaya/E/Rockchip/3566/Android/kernel
#ARCH ?= arm64
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3566/Android/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
#KDIR ?= /home/yaya/E/Rockchip/3328/Android9/SDK/kernel/
#ARCH ?= arm64
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3328/Android9/SDK/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
#KDIR ?= /home/yaya/E/Rockchip/3566/oudu/kernel
KDIR ?= ~/E/Rockchip/3566/Android11/rk3566_rk3568_android11_oranth/kernel
#KDIR ?= /home/yaya/E/Rockchip/3566/shengteng/kernel
ARCH ?= arm64
CROSS_COMPILE ?= ~/E/Rockchip/3566/Android11/rk3566_rk3568_android11_oranth/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP
ccflags-y += -DANDROID_PLATFORM
endif
ifeq ($(CONFIG_PLATFORM_ALLWINNER), y)
ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER
ccflags-y += -DANDROID_PLATFORM
KDIR ?= /home/yaya/E/Allwinner/r818/Android10/lichee/kernel/linux-4.9/
ARCH ?= arm64
CROSS_COMPILE ?= /home/yaya/E/Allwinner/r818/Android10/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-
endif
ifeq ($(CONFIG_PLATFORM_INGENIC_T20), y)
KDIR ?= /home/yaya/E/T40/kernel
ARCH ?= mips
CROSS_COMPILE ?= /home/yaya/E/T40/mips-linux-gnu-ingenic-gcc7.2.0-glibc2.29-fp64/bin/mips-linux-gnu-
endif
ifeq ($(CONFIG_PLATFORM_AMLOGIC), y)
ccflags-$(CONFIG_PLATFORM_AMLOGIC) += -DCONFIG_PLATFORM_AMLOGIC
ccflags-y += -DANDROID_PLATFORM
endif
ifeq ($(CONFIG_PLATFORM_UBUNTU), y)
KDIR ?= /lib/modules/$(shell uname -r)/build
PWD ?= $(shell pwd)
KVER ?= $(shell uname -r)
MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/
ARCH ?= x86_64
CROSS_COMPILE ?=
endif
all: modules
modules:
make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
install:
mkdir -p $(MODDESTDIR)
install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR)
/sbin/depmod -a ${KVER}
uninstall:
rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko
/sbin/depmod -a ${KVER}
clean:
rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#ifndef _AIC_BR_EXT_H_
#define _AIC_BR_EXT_H_
#define CL_IPV6_PASS 1
#define MACADDRLEN 6
#define WLAN_ETHHDR_LEN 14
#define NAT25_HASH_BITS 4
#define NAT25_HASH_SIZE (1 << NAT25_HASH_BITS)
#define NAT25_AGEING_TIME 300
#define NDEV_FMT "%s"
#define NDEV_ARG(ndev) ndev->name
#define ADPT_FMT "%s"
//#define ADPT_ARG(adapter) (adapter->pnetdev ? adapter->pnetdev->name : NULL)
#define FUNC_NDEV_FMT "%s(%s)"
#define FUNC_NDEV_ARG(ndev) __func__, ndev->name
#define FUNC_ADPT_FMT "%s(%s)"
//#define FUNC_ADPT_ARG(adapter) __func__, (adapter->pnetdev ? adapter->pnetdev->name : NULL)
#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
#define MAC_ARG(x) ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2], ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5]
#ifdef CL_IPV6_PASS
#define MAX_NETWORK_ADDR_LEN 17
#else
#define MAX_NETWORK_ADDR_LEN 11
#endif
struct nat25_network_db_entry {
struct nat25_network_db_entry *next_hash;
struct nat25_network_db_entry **pprev_hash;
atomic_t use_count;
unsigned char macAddr[6];
unsigned long ageing_timer;
unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
};
enum NAT25_METHOD {
NAT25_MIN,
NAT25_CHECK,
NAT25_INSERT,
NAT25_LOOKUP,
NAT25_PARSE,
NAT25_MAX
};
struct br_ext_info {
unsigned int nat25_disable;
unsigned int macclone_enable;
unsigned int dhcp_bcst_disable;
int addPPPoETag; /* 1: Add PPPoE relay-SID, 0: disable */
unsigned char nat25_dmzMac[MACADDRLEN];
unsigned int nat25sc_disable;
};
void nat25_db_cleanup(struct rwnx_vif *vif);
#endif /* _AIC_BR_EXT_H_ */

View File

@@ -0,0 +1,33 @@
#ifndef __AIC_BSP_EXPORT_H
#define __AIC_BSP_EXPORT_H
#define AICBSP_RESV_MEM_SUPPORT 0
enum aicbsp_subsys {
AIC_BLUETOOTH,
AIC_WIFI,
};
enum aicbsp_pwr_state {
AIC_PWR_OFF,
AIC_PWR_ON,
};
struct aicbsp_feature_t {
int hwinfo;
uint32_t sdio_clock;
uint8_t sdio_phase;
int fwlog_en;
};
enum skb_buff_id {
AIC_RESV_MEM_TXDATA,
};
int aicbsp_set_subsys(int, int);
int aicbsp_get_feature(struct aicbsp_feature_t *feature, char *fw_path);
bool aicbsp_get_load_fw_in_fdrv(void);
struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id);
void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id);
#endif

View File

@@ -0,0 +1,877 @@
#include "aic_vendor.h"
#include "rwnx_defs.h"
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/rtnetlink.h>
#include <net/netlink.h>
#include "rwnx_version_gen.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
static struct wifi_ring_buffer_status ring_buffer[] = {
{
.name = "aicwf_ring_buffer0",
.flags = 0,
.ring_id = 0,
.verbose_level = 0,
.written_bytes = 0,
.read_bytes = 0,
.written_records = 0,
},
};
static struct wlan_driver_wake_reason_cnt_t wake_reason_cnt = {
.total_cmd_event_wake = 10,
};
#endif
int aic_dev_start_mkeep_alive(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
u8 mkeep_alive_id, u8 *ip_pkt, u16 ip_pkt_len, u8 *src_mac, u8 *dst_mac, u32 period_msec)
{
u8 *data, *pos;
data = kzalloc(ip_pkt_len + 14, GFP_KERNEL);
if (!data)
return -ENOMEM;
pos = data;
memcpy(pos, dst_mac, 6);
pos += 6;
memcpy(pos, src_mac, 6);
pos += 6;
/* Mapping Ethernet type (ETHERTYPE_IP: 0x0800) */
*(pos++) = 0x08;
*(pos++) = 0x00;
/* Mapping IP pkt */
memcpy(pos, ip_pkt, ip_pkt_len);
pos += ip_pkt_len;
//add send 802.3 pkt(raw data)
kfree(data);
return 0;
}
int aic_dev_stop_mkeep_alive(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, u8 mkeep_alive_id)
{
int res = -1;
/*
* The mkeep_alive packet is for STA interface only; if the bss is configured as AP,
* dongle shall reject a mkeep_alive request.
*/
if (rwnx_vif->wdev.iftype != NL80211_IFTYPE_STATION)
return res;
printk("%s execution\n", __func__);
//add send stop keep alive
res = 0;
return res;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
static int aicwf_vendor_start_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev,
const void *data, int len)
{
/* max size of IP packet for keep alive */
const int MKEEP_ALIVE_IP_PKT_MAX = 256;
int ret = 0, rem, type;
u8 mkeep_alive_id = 0;
u8 *ip_pkt = NULL;
u16 ip_pkt_len = 0;
u8 src_mac[6];
u8 dst_mac[6];
u32 period_msec = 0;
const struct nlattr *iter;
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev);
gfp_t kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
printk("%s\n", __func__);
nla_for_each_attr(iter, data, len, rem) {
type = nla_type(iter);
switch (type) {
case MKEEP_ALIVE_ATTRIBUTE_ID:
mkeep_alive_id = nla_get_u8(iter);
break;
case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN:
ip_pkt_len = nla_get_u16(iter);
if (ip_pkt_len > MKEEP_ALIVE_IP_PKT_MAX) {
ret = -EINVAL;
goto exit;
}
break;
case MKEEP_ALIVE_ATTRIBUTE_IP_PKT:
if (!ip_pkt_len) {
ret = -EINVAL;
printk("ip packet length is 0\n");
goto exit;
}
ip_pkt = (u8 *)kzalloc(ip_pkt_len, kflags);
if (ip_pkt == NULL) {
ret = -ENOMEM;
printk("Failed to allocate mem for ip packet\n");
goto exit;
}
memcpy(ip_pkt, (u8 *)nla_data(iter), ip_pkt_len);
break;
case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR:
memcpy(src_mac, nla_data(iter), 6);
break;
case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR:
memcpy(dst_mac, nla_data(iter), 6);
break;
case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC:
period_msec = nla_get_u32(iter);
break;
default:
pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
ret = -EINVAL;
goto exit;
}
}
if (ip_pkt == NULL) {
ret = -EINVAL;
printk("ip packet is NULL\n");
goto exit;
}
ret = aic_dev_start_mkeep_alive(rwnx_hw, rwnx_vif, mkeep_alive_id, ip_pkt, ip_pkt_len, src_mac,
dst_mac, period_msec);
if (ret < 0) {
printk("start_mkeep_alive is failed ret: %d\n", ret);
}
exit:
if (ip_pkt) {
kfree(ip_pkt);
}
return ret;
}
static int aicwf_vendor_stop_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev,
const void *data, int len)
{
int ret = 0, rem, type;
u8 mkeep_alive_id = 0;
const struct nlattr *iter;
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev);
printk("%s\n", __func__);
nla_for_each_attr(iter, data, len, rem) {
type = nla_type(iter);
switch (type) {
case MKEEP_ALIVE_ATTRIBUTE_ID:
mkeep_alive_id = nla_get_u8(iter);
break;
default:
pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
ret = -EINVAL;
break;
}
}
ret = aic_dev_stop_mkeep_alive(rwnx_hw, rwnx_vif, mkeep_alive_id);
if (ret < 0) {
printk("stop_mkeep_alive is failed ret: %d\n", ret);
}
return ret;
}
static int aicwf_vendor_get_ver(struct wiphy *wiphy, struct wireless_dev *wdev,
const void *data, int len)
{
int ret = 0, rem, type;
const struct nlattr *iter;
int payload = 0;
char version[128];
int attr = -1;
struct sk_buff *reply;
nla_for_each_attr(iter, data, len, rem) {
type = nla_type(iter);
switch (type) {
case LOGGER_ATTRIBUTE_DRIVER_VER:
memcpy(version, RWNX_VERS_BANNER, sizeof(RWNX_VERS_BANNER));
payload = strlen(version);
attr = LOGGER_ATTRIBUTE_DRIVER_VER;
break;
case LOGGER_ATTRIBUTE_FW_VER:
memcpy(version, wiphy->fw_version, sizeof(wiphy->fw_version));
payload = strlen(version);
attr = LOGGER_ATTRIBUTE_FW_VER;
break;
default:
AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
return -EINVAL;
}
}
if (attr < 0)
return -EINVAL;
reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
if (!reply)
return -ENOMEM;
if (nla_put(reply, attr,
payload, version)) {
wiphy_err(wiphy, "%s put version error\n", __func__);
goto out_put_fail;
}
ret = cfg80211_vendor_cmd_reply(reply);
if (ret)
wiphy_err(wiphy, "%s reply cmd error\n", __func__);
return ret;
out_put_fail:
kfree_skb(reply);
return -EMSGSIZE;
}
static int aicwf_vendor_subcmd_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev,
const void *data, int len)
{
int ret = 0, rem, type;
const struct nlattr *iter;
struct sk_buff *reply;
int num_channels = 0;
int *channel_list = NULL;
int payload;
int i = 0;
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ];
struct ieee80211_supported_band *rwnx_band_5GHz = rwnx_hw->wiphy->bands[NL80211_BAND_5GHZ];
num_channels += rwnx_band_2GHz->n_channels;
num_channels += (rwnx_hw->band_5g_support) ? rwnx_band_5GHz->n_channels : 0;
channel_list = (int *)kzalloc(sizeof(int) * num_channels, GFP_KERNEL);
if (!channel_list)
return -ENOMEM;
for (i = 0; i < rwnx_band_2GHz->n_channels; i++)
channel_list[i] = rwnx_band_2GHz->channels[i].center_freq;
for (; rwnx_hw->band_5g_support && i < num_channels; i++)
channel_list[i] = rwnx_band_5GHz->channels[i].center_freq;
payload = sizeof(num_channels) + sizeof(int) * num_channels + 4;
nla_for_each_attr(iter, data, len, rem) {
type = nla_type(iter);
switch (type) {
case GSCAN_ATTRIBUTE_BAND:
reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
if (!reply)
return -ENOMEM;
if (nla_put_u32(reply, GSCAN_ATTRIBUTE_NUM_CHANNELS, num_channels))
goto out_put_fail;
if (nla_put(reply, GSCAN_ATTRIBUTE_CHANNEL_LIST, sizeof(int) * num_channels, channel_list))
goto out_put_fail;
ret = cfg80211_vendor_cmd_reply(reply);
if (ret)
wiphy_err(wiphy, "%s reply cmd error\n", __func__);
break;
default:
pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
return -EINVAL;
}
}
kfree(channel_list);
return ret;
out_put_fail:
kfree(channel_list);
kfree_skb(reply);
return -EMSGSIZE;
}
static int aicwf_vendor_subcmd_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev,
const void *data, int len)
{
int ret = 0, rem, type;
const struct nlattr *iter;
nla_for_each_attr(iter, data, len, rem) {
type = nla_type(iter);
switch (type) {
case ANDR_WIFI_ATTRIBUTE_COUNTRY:
printk("%s(%d), ANDR_WIFI_ATTRIBUTE_COUNTRY: %s\n", __func__, __LINE__, (char *)nla_data(iter));
break;
default:
pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
return -EINVAL;
}
}
/* TODO
* Add handle in the future!
*/
return ret;
}
static int aicwf_vendor_logger_trigger_memory_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
const void *data, int len)
{
/* TODO
* Add handle in the future!
*/
return 0;
}
static int aicwf_vendor_subcmd_get_feature_set(struct wiphy *wiphy, struct wireless_dev *wdev,
const void *data, int len)
{
int ret;
struct sk_buff *reply;
uint32_t feature = 0, payload;
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
payload = sizeof(feature);
reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
if (!reply)
return -ENOMEM;
/* TODO
* Add handle in the future!
*/
/*bit 1:Basic infrastructure mode*/
if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION))
feature |= WIFI_FEATURE_INFRA;
/*bit 2:Support for 5 GHz Band*/
if (rwnx_hw->band_5g_support)
feature |= WIFI_FEATURE_INFRA_5G;
/*bit3:HOTSPOT is a supplicant feature, enable it by default*/
feature |= WIFI_FEATURE_HOTSPOT;
/*bit 4:P2P*/
if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
(wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO)))
feature |= WIFI_FEATURE_P2P;
/*bit 5:soft AP feature supported*/
if (wiphy->interface_modes & BIT(NL80211_IFTYPE_AP))
feature |= WIFI_FEATURE_SOFT_AP;
/*bit 18:WiFi Logger*/
feature |= WIFI_FEATURE_LOGGER;
/*bit 21:WiFi mkeep_alive*/
feature |= WIFI_FEATURE_MKEEP_ALIVE;
if (nla_put_u32(reply, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, feature)) {
wiphy_err(wiphy, "%s put u32 error\n", __func__);
goto out_put_fail;
}
ret = cfg80211_vendor_cmd_reply(reply);
if (ret)
wiphy_err(wiphy, "%s reply cmd error\n", __func__);
return ret;
out_put_fail:
kfree_skb(reply);
return -EMSGSIZE;
}
static int aicwf_vendor_logger_get_feature(struct wiphy *wiphy, struct wireless_dev *wdev,
const void *data, int len)
{
int ret;
struct sk_buff *reply;
uint32_t feature = 0, payload;
payload = sizeof(feature);
reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
if (!reply)
return -ENOMEM;
feature |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
feature |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
/*vts will test wake reason state function*/
feature |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
if (nla_put_u32(reply, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, feature)) {
wiphy_err(wiphy, "put skb u32 failed\n");
goto out_put_fail;
}
ret = cfg80211_vendor_cmd_reply(reply);
if (ret)
wiphy_err(wiphy, "reply cmd error\n");
return ret;
out_put_fail:
kfree_skb(reply);
return -EMSGSIZE;
}
static int aicwf_vendor_logger_get_ring_status(struct wiphy *wiphy, struct wireless_dev *wdev,
const void *data, int len)
{
int ret;
struct sk_buff *reply;
uint32_t payload;
uint32_t ring_buffer_nums = sizeof(ring_buffer) / sizeof(ring_buffer[0]);
payload = sizeof(ring_buffer_nums) + sizeof(ring_buffer);
reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
if (!reply)
return -ENOMEM;
if (nla_put_u32(reply, LOGGER_ATTRIBUTE_RING_NUM, ring_buffer_nums)) {
wiphy_err(wiphy, "put skb u32 failed\n");
goto out_put_fail;
}
if (nla_put(reply, LOGGER_ATTRIBUTE_RING_STATUS, sizeof(ring_buffer), ring_buffer)) {
wiphy_err(wiphy, "put skb failed\n");
goto out_put_fail;
}
ret = cfg80211_vendor_cmd_reply(reply);
if (ret)
wiphy_err(wiphy, "reply cmd error\n");
return ret;
out_put_fail:
kfree_skb(reply);
return -EMSGSIZE;
}
static int aicwf_vendor_logger_start_logging(struct wiphy *wiphy, struct wireless_dev *wdev,
const void *data, int len)
{
int ret = 0, rem, type, intval, size, i;
const struct nlattr *iter;
struct wifi_ring_buffer_status rb;
nla_for_each_attr(iter, data, len, rem) {
type = nla_type(iter);
switch (type) {
case LOGGER_ATTRIBUTE_LOG_LEVEL:
rb.verbose_level = nla_get_u32(iter);
break;
case LOGGER_ATTRIBUTE_RING_FLAGS:
rb.flags = nla_get_u32(iter);
break;
case LOGGER_ATTRIBUTE_LOG_TIME_INTVAL:
intval = nla_get_u32(iter);
break;
case LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE:
size = nla_get_u32(iter);
break;
case LOGGER_ATTRIBUTE_RING_NAME:
strcpy(rb.name, nla_data(iter));
break;
default:
AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
return -EINVAL;
}
}
ret = -EINVAL;
for (i = 0; i < sizeof(ring_buffer) / sizeof(ring_buffer[0]); i++) {
if (strcmp(rb.name, ring_buffer[i].name) == 0) {
ret = 0;
break;
}
}
/* TODO
* Add handle in the future
*/
return ret;
}
static int aicwf_vendor_logger_get_ring_data(struct wiphy *wiphy, struct wireless_dev *wdev,
const void *data, int len)
{
int ret = 0, rem, type, i;
const struct nlattr *iter;
struct wifi_ring_buffer_status rb;
nla_for_each_attr(iter, data, len, rem) {
type = nla_type(iter);
switch (type) {
case LOGGER_ATTRIBUTE_RING_NAME:
strcpy(rb.name, nla_data(iter));
break;
default:
pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
return -EINVAL;
}
}
ret = -EINVAL;
for (i = 0; i < sizeof(ring_buffer) / sizeof(ring_buffer[0]); i++) {
if (strcmp(rb.name, ring_buffer[i].name) == 0) {
ret = 0;
break;
}
}
/* TODO
* Add handle in the future
*/
return ret;
}
static int aicwf_vendor_logger_get_wake_reason_stats(struct wiphy *wiphy, struct wireless_dev *wdev,
const void *data, int len)
{
int ret;
struct sk_buff *reply;
uint32_t payload;
payload = sizeof(wake_reason_cnt.total_cmd_event_wake);
reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
if (!reply)
return -ENOMEM;
/* TODO
* Add handle in the future
*/
if (nla_put_u32(reply, WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT, wake_reason_cnt.total_cmd_event_wake))
goto out_put_fail;
ret = cfg80211_vendor_cmd_reply(reply);
if (ret)
wiphy_err(wiphy, "reply cmd error\n");
return ret;
out_put_fail:
kfree_skb(reply);
return -EMSGSIZE;
}
static int aicwf_vendor_apf_subcmd_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev,
const void *data, int len)
{
/* TODO
* Add handle in the future
*/
return 0;
}
static int aicwf_vendor_sub_cmd_set_mac(struct wiphy *wiphy, struct wireless_dev *wdev,
const void *data, int len)
{
int ret = 0, rem, type;
const struct nlattr *iter;
u8 mac[ETH_ALEN];
nla_for_each_attr(iter, data, len, rem) {
type = nla_type(iter);
switch (type) {
case WIFI_VENDOR_ATTR_DRIVER_MAC_ADDR:
memcpy(mac, nla_data(iter), ETH_ALEN);
printk("%s, %02X:%02X:%02X:%02X:%02X:%02X\n", __func__,
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
break;
default:
pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
return -EINVAL;
}
}
/* TODO
* Add handle in the future
*/
return ret;
}
#endif
static const struct nla_policy
aicwf_cfg80211_mkeep_alive_policy[MKEEP_ALIVE_ATTRIBUTE_MAX+1] = {
[0] = {.type = NLA_UNSPEC },
[MKEEP_ALIVE_ATTRIBUTE_ID] = { .type = NLA_U8 },
[MKEEP_ALIVE_ATTRIBUTE_IP_PKT] = { .type = NLA_MSECS },
[MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN] = { .type = NLA_U16 },
[MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR] = { .type = NLA_MSECS,
.len = ETH_ALEN },
[MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR] = { .type = NLA_MSECS,
.len = ETH_ALEN },
[MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC] = { .type = NLA_U32 },
};
static const struct nla_policy
aicwf_cfg80211_logger_policy[LOGGER_ATTRIBUTE_MAX + 1] = {
[0] = {.type = NLA_UNSPEC },
[LOGGER_ATTRIBUTE_DRIVER_VER] = { .type = NLA_BINARY },
[LOGGER_ATTRIBUTE_FW_VER] = { .type = NLA_BINARY },
[LOGGER_ATTRIBUTE_LOG_LEVEL] = { .type = NLA_U32 },
[LOGGER_ATTRIBUTE_RING_FLAGS] = { .type = NLA_U32 },
[LOGGER_ATTRIBUTE_LOG_TIME_INTVAL] = { .type = NLA_U32 },
[LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE] = { .type = NLA_U32 },
[LOGGER_ATTRIBUTE_RING_NAME] = { .type = NLA_STRING },
};
static const struct nla_policy
aicwf_cfg80211_subcmd_policy[GSCAN_ATTRIBUTE_MAX + 1] = {
[0] = {.type = NLA_UNSPEC },
[GSCAN_ATTRIBUTE_BAND] = { .type = NLA_U32 },
};
static const struct nla_policy
aicwf_cfg80211_andr_wifi_policy[ANDR_WIFI_ATTRIBUTE_MAX + 1] = {
[0] = {.type = NLA_UNSPEC },
[ANDR_WIFI_ATTRIBUTE_COUNTRY] = { .type = NLA_STRING },
};
static const struct nla_policy
aicwf_cfg80211_subcmd_set_mac_policy[WIFI_VENDOR_ATTR_DRIVER_MAX + 1] = {
[0] = {.type = NLA_UNSPEC },
[WIFI_VENDOR_ATTR_DRIVER_MAC_ADDR] = { .type = NLA_MSECS, .len = ETH_ALEN },
};
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
static int aicwf_dump_interface(struct wiphy *wiphy,
struct wireless_dev *wdev, struct sk_buff *skb,
const void *data, int data_len,
unsigned long *storage)
{
return 0;
}
const struct wiphy_vendor_command aicwf_vendor_cmd[] = {
{
{
.vendor_id = GOOGLE_OUI,
.subcmd = WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = aicwf_vendor_start_mkeep_alive,
.dumpit = aicwf_dump_interface,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
.policy = aicwf_cfg80211_mkeep_alive_policy,
.maxattr = MKEEP_ALIVE_ATTRIBUTE_MAX
#endif
},
{
{
.vendor_id = GOOGLE_OUI,
.subcmd = WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = aicwf_vendor_stop_mkeep_alive,
.dumpit = aicwf_dump_interface,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
.policy = aicwf_cfg80211_mkeep_alive_policy,
.maxattr = MKEEP_ALIVE_ATTRIBUTE_MAX
#endif
},
{
{
.vendor_id = GOOGLE_OUI,
.subcmd = LOGGER_GET_VER
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = aicwf_vendor_get_ver,
.dumpit = aicwf_dump_interface,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
.policy = aicwf_cfg80211_logger_policy,
.maxattr = LOGGER_ATTRIBUTE_MAX
#endif
},
{
{
.vendor_id = GOOGLE_OUI,
.subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = aicwf_vendor_subcmd_get_channel_list,
.dumpit = aicwf_dump_interface,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
.policy = aicwf_cfg80211_subcmd_policy,
.maxattr = GSCAN_ATTRIBUTE_MAX
#endif
},
{
{
.vendor_id = GOOGLE_OUI,
.subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = aicwf_vendor_subcmd_set_country_code,
.dumpit = aicwf_dump_interface,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
.policy = aicwf_cfg80211_andr_wifi_policy,
.maxattr = ANDR_WIFI_ATTRIBUTE_MAX
#endif
},
{
{
.vendor_id = GOOGLE_OUI,
.subcmd = LOGGER_TRIGGER_MEM_DUMP
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = aicwf_vendor_logger_trigger_memory_dump,
.dumpit = aicwf_dump_interface,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
.policy = VENDOR_CMD_RAW_DATA,
#endif
},
{
{
.vendor_id = GOOGLE_OUI,
.subcmd = WIFI_SUBCMD_GET_FEATURE_SET
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = aicwf_vendor_subcmd_get_feature_set,
.dumpit = aicwf_dump_interface,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
.policy = VENDOR_CMD_RAW_DATA,
#endif
},
{
{
.vendor_id = GOOGLE_OUI,
.subcmd = LOGGER_GET_FEATURE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = aicwf_vendor_logger_get_feature,
.dumpit = aicwf_dump_interface,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
.policy = VENDOR_CMD_RAW_DATA,
#endif
},
{
{
.vendor_id = GOOGLE_OUI,
.subcmd = LOGGER_GET_RING_STATUS
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = aicwf_vendor_logger_get_ring_status,
.dumpit = aicwf_dump_interface,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
.policy = VENDOR_CMD_RAW_DATA,
#endif
},
{
{
.vendor_id = GOOGLE_OUI,
.subcmd = LOGGER_START_LOGGING
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = aicwf_vendor_logger_start_logging,
.dumpit = aicwf_dump_interface,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
.policy = aicwf_cfg80211_logger_policy,
.maxattr = LOGGER_ATTRIBUTE_MAX
#endif
},
{
{
.vendor_id = GOOGLE_OUI,
.subcmd = LOGGER_GET_RING_DATA
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = aicwf_vendor_logger_get_ring_data,
.dumpit = aicwf_dump_interface,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
.policy = aicwf_cfg80211_logger_policy,
.maxattr = LOGGER_ATTRIBUTE_MAX
#endif
},
{
{
.vendor_id = GOOGLE_OUI,
.subcmd = LOGGER_GET_WAKE_REASON_STATS
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = aicwf_vendor_logger_get_wake_reason_stats,
.dumpit = aicwf_dump_interface,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
.policy = VENDOR_CMD_RAW_DATA,
#endif
},
{
{
.vendor_id = GOOGLE_OUI,
.subcmd = APF_SUBCMD_GET_CAPABILITIES
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = aicwf_vendor_apf_subcmd_get_capabilities,
.dumpit = aicwf_dump_interface,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
.policy = VENDOR_CMD_RAW_DATA,
#endif
},
{
{
.vendor_id = GOOGLE_OUI,
.subcmd = VENDOR_NL80211_SUBCMD_SET_MAC
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
.doit = aicwf_vendor_sub_cmd_set_mac,
.dumpit = aicwf_dump_interface,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
.policy = aicwf_cfg80211_subcmd_set_mac_policy,
.maxattr = WIFI_VENDOR_ATTR_DRIVER_MAX,
#endif
},
{
{
.vendor_id = BRCM_OUI,
.subcmd = VENDOR_NL80211_SUBCMD_SET_MAC
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
.doit = aicwf_vendor_sub_cmd_set_mac,
.dumpit = aicwf_dump_interface,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
.policy = aicwf_cfg80211_subcmd_set_mac_policy,
.maxattr = WIFI_VENDOR_ATTR_DRIVER_MAX,
#endif
},
};
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
static const struct nl80211_vendor_cmd_info aicwf_vendor_events[] = {
};
#endif
int aicwf_vendor_init(struct wiphy *wiphy)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
wiphy->vendor_commands = aicwf_vendor_cmd;
wiphy->n_vendor_commands = ARRAY_SIZE(aicwf_vendor_cmd);
wiphy->vendor_events = aicwf_vendor_events;
wiphy->n_vendor_events = ARRAY_SIZE(aicwf_vendor_events);
#endif
return 0;
}

View File

@@ -0,0 +1,346 @@
#ifndef _AIC_VENDOR_H
#define _AIC_VENDOR_H
#include <linux/types.h>
#define GOOGLE_OUI 0x001A11
#define BRCM_OUI 0x001018
typedef enum {
START_MKEEP_ALIVE,
STOP_MKEEP_ALIVE,
} GetCmdType;
typedef enum {
/* don't use 0 as a valid subcommand */
VENDOR_NL80211_SUBCMD_UNSPECIFIED,
/* define all vendor startup commands between 0x0 and 0x0FFF */
VENDOR_NL80211_SUBCMD_RANGE_START = 0x0001,
VENDOR_NL80211_SUBCMD_RANGE_END = 0x0FFF,
/* define all GScan related commands between 0x1000 and 0x10FF */
ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000,
ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF,
/* define all NearbyDiscovery related commands between 0x1100 and 0x11FF */
ANDROID_NL80211_SUBCMD_NBD_RANGE_START = 0x1100,
ANDROID_NL80211_SUBCMD_NBD_RANGE_END = 0x11FF,
/* define all RTT related commands between 0x1100 and 0x11FF */
ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100,
ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF,
ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200,
ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF,
/* define all Logger related commands between 0x1400 and 0x14FF */
ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400,
ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END = 0x14FF,
/* define all wifi offload related commands between 0x1600 and 0x16FF */
ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600,
ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END = 0x16FF,
/* define all NAN related commands between 0x1700 and 0x17FF */
ANDROID_NL80211_SUBCMD_NAN_RANGE_START = 0x1700,
ANDROID_NL80211_SUBCMD_NAN_RANGE_END = 0x17FF,
/* define all Android Packet Filter related commands between 0x1800 and 0x18FF */
ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START = 0x1800,
ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_END = 0x18FF,
/* This is reserved for future usage */
} ANDROID_VENDOR_SUB_COMMAND;
typedef enum {
WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE = ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START,
WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE,
} WIFI_OFFLOAD_SUB_COMMAND;
enum mkeep_alive_attributes {
MKEEP_ALIVE_ATTRIBUTE_ID = 0x1,
MKEEP_ALIVE_ATTRIBUTE_IP_PKT,
MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN,
MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR,
MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR,
MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC,
MKEEP_ALIVE_ATTRIBUTE_AFTER_LAST,
MKEEP_ALIVE_ATTRIBUTE_MAX = MKEEP_ALIVE_ATTRIBUTE_AFTER_LAST - 1
};
enum debug_sub_command {
LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
LOGGER_TRIGGER_MEM_DUMP,
LOGGER_GET_MEM_DUMP,
LOGGER_GET_VER,
LOGGER_GET_RING_STATUS,
LOGGER_GET_RING_DATA,
LOGGER_GET_FEATURE,
LOGGER_RESET_LOGGING,
LOGGER_TRIGGER_DRIVER_MEM_DUMP,
LOGGER_GET_DRIVER_MEM_DUMP,
LOGGER_START_PKT_FATE_MONITORING,
LOGGER_GET_TX_PKT_FATES,
LOGGER_GET_RX_PKT_FATES,
LOGGER_GET_WAKE_REASON_STATS,
LOGGER_DEBUG_GET_DUMP,
LOGGER_FILE_DUMP_DONE_IND,
LOGGER_SET_HAL_START,
LOGGER_HAL_STOP,
LOGGER_SET_HAL_PID,
};
enum logger_attributes {
LOGGER_ATTRIBUTE_INVALID = 0,
LOGGER_ATTRIBUTE_DRIVER_VER,
LOGGER_ATTRIBUTE_FW_VER,
LOGGER_ATTRIBUTE_RING_ID,
LOGGER_ATTRIBUTE_RING_NAME,
LOGGER_ATTRIBUTE_RING_FLAGS,
LOGGER_ATTRIBUTE_LOG_LEVEL,
LOGGER_ATTRIBUTE_LOG_TIME_INTVAL,
LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE,
LOGGER_ATTRIBUTE_FW_DUMP_LEN,
LOGGER_ATTRIBUTE_FW_DUMP_DATA,
// LOGGER_ATTRIBUTE_FW_ERR_CODE,
LOGGER_ATTRIBUTE_RING_DATA,
LOGGER_ATTRIBUTE_RING_STATUS,
LOGGER_ATTRIBUTE_RING_NUM,
LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN,
LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA,
LOGGER_ATTRIBUTE_PKT_FATE_NUM,
LOGGER_ATTRIBUTE_PKT_FATE_DATA,
LOGGER_ATTRIBUTE_AFTER_LAST,
LOGGER_ATTRIBUTE_MAX = LOGGER_ATTRIBUTE_AFTER_LAST - 1,
};
enum wifi_sub_command {
GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START,
GSCAN_SUBCMD_SET_CONFIG, /* 0x1001 */
GSCAN_SUBCMD_SET_SCAN_CONFIG, /* 0x1002 */
GSCAN_SUBCMD_ENABLE_GSCAN, /* 0x1003 */
GSCAN_SUBCMD_GET_SCAN_RESULTS, /* 0x1004 */
GSCAN_SUBCMD_SCAN_RESULTS, /* 0x1005 */
GSCAN_SUBCMD_SET_HOTLIST, /* 0x1006 */
GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG, /* 0x1007 */
GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, /* 0x1008 */
GSCAN_SUBCMD_GET_CHANNEL_LIST, /* 0x1009 */
WIFI_SUBCMD_GET_FEATURE_SET, /* 0x100A */
WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x100B */
WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x100C */
WIFI_SUBCMD_NODFS_SET, /* 0x100D */
WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x100E */
/* Add more sub commands here */
GSCAN_SUBCMD_SET_EPNO_SSID, /* 0x100F */
WIFI_SUBCMD_SET_SSID_WHITE_LIST, /* 0x1010 */
WIFI_SUBCMD_SET_ROAM_PARAMS, /* 0x1011 */
WIFI_SUBCMD_ENABLE_LAZY_ROAM, /* 0x1012 */
WIFI_SUBCMD_SET_BSSID_PREF, /* 0x1013 */
WIFI_SUBCMD_SET_BSSID_BLACKLIST, /* 0x1014 */
GSCAN_SUBCMD_ANQPO_CONFIG, /* 0x1015 */
WIFI_SUBCMD_SET_RSSI_MONITOR, /* 0x1016 */
WIFI_SUBCMD_CONFIG_ND_OFFLOAD, /* 0x1017 */
/* Add more sub commands here */
GSCAN_SUBCMD_MAX,
APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START,
APF_SUBCMD_SET_FILTER,
};
enum gscan_attributes {
GSCAN_ATTRIBUTE_NUM_BUCKETS = 10,
GSCAN_ATTRIBUTE_BASE_PERIOD,
GSCAN_ATTRIBUTE_BUCKETS_BAND,
GSCAN_ATTRIBUTE_BUCKET_ID,
GSCAN_ATTRIBUTE_BUCKET_PERIOD,
GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
GSCAN_ATTRIBUTE_BUCKET_CHANNELS,
GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN,
GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE,
GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND,
GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20,
GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */
GSCAN_ATTRIBUTE_FLUSH_FEATURE, /* Flush all the configs */
GSCAN_ENABLE_FULL_SCAN_RESULTS,
GSCAN_ATTRIBUTE_REPORT_EVENTS,
/* remaining reserved for additional attributes */
GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30,
GSCAN_ATTRIBUTE_FLUSH_RESULTS,
GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */
GSCAN_ATTRIBUTE_SCAN_ID, /* indicates scan number */
GSCAN_ATTRIBUTE_SCAN_FLAGS, /* indicates if scan was aborted */
GSCAN_ATTRIBUTE_AP_FLAGS, /* flags on significant change event */
GSCAN_ATTRIBUTE_NUM_CHANNELS,
GSCAN_ATTRIBUTE_CHANNEL_LIST,
GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK,
GSCAN_ATTRIBUTE_AFTER_LAST,
GSCAN_ATTRIBUTE_MAX = GSCAN_ATTRIBUTE_AFTER_LAST - 1,
};
enum andr_wifi_attributes {
ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
ANDR_WIFI_ATTRIBUTE_FEATURE_SET,
ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI,
ANDR_WIFI_ATTRIBUTE_NODFS_SET,
ANDR_WIFI_ATTRIBUTE_COUNTRY,
ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE,
// Add more attribute here
ANDR_WIFI_ATTRIBUTE_AFTER_LAST,
ANDR_WIFI_ATTRIBUTE_MAX = ANDR_WIFI_ATTRIBUTE_AFTER_LAST - 1,
};
enum wifi_support_feature {
/* Feature enums */
WIFI_FEATURE_INFRA = 0x0001, /* Basic infrastructure mode */
WIFI_FEATURE_INFRA_5G = 0x0002, /* Support for 5, GHz Band */
WIFI_FEATURE_HOTSPOT = 0x0004, /* Support for GAS/ANQP */
WIFI_FEATURE_P2P = 0x0008, /* Wifi-Direct */
WIFI_FEATURE_SOFT_AP = 0x0010, /* Soft AP */
WIFI_FEATURE_GSCAN = 0x0020, /* Google-Scan APIs */
WIFI_FEATURE_NAN = 0x0040, /* Neighbor Awareness Networking */
WIFI_FEATURE_D2D_RTT = 0x0080, /* Device-to-device RTT */
WIFI_FEATURE_D2AP_RTT = 0x0100, /* Device-to-AP RTT */
WIFI_FEATURE_BATCH_SCAN = 0x0200, /* Batched Scan (legacy) */
WIFI_FEATURE_PNO = 0x0400, /* Preferred network offload */
WIFI_FEATURE_ADDITIONAL_STA = 0x0800, /* Support for two STAs */
WIFI_FEATURE_TDLS = 0x1000, /* Tunnel directed link setup */
WIFI_FEATURE_TDLS_OFFCHANNEL = 0x2000, /* Support for TDLS off channel */
WIFI_FEATURE_EPR = 0x4000, /* Enhanced power reporting */
WIFI_FEATURE_AP_STA = 0x8000, /* Support for AP STA Concurrency */
WIFI_FEATURE_LINK_LAYER_STATS = 0x10000, /* Support for Linkstats */
WIFI_FEATURE_LOGGER = 0x20000, /* WiFi Logger */
WIFI_FEATURE_HAL_EPNO = 0x40000, /* WiFi PNO enhanced */
WIFI_FEATURE_RSSI_MONITOR = 0x80000, /* RSSI Monitor */
WIFI_FEATURE_MKEEP_ALIVE = 0x100000, /* WiFi mkeep_alive */
WIFI_FEATURE_CONFIG_NDO = 0x200000, /* ND offload configure */
WIFI_FEATURE_TX_TRANSMIT_POWER = 0x400000, /* Capture Tx transmit power levels */
WIFI_FEATURE_CONTROL_ROAMING = 0x800000, /* Enable/Disable firmware roaming */
WIFI_FEATURE_IE_WHITELIST = 0x1000000, /* Support Probe IE white listing */
WIFI_FEATURE_SCAN_RAND = 0x2000000, /* Support MAC & Probe Sequence Number randomization */
WIFI_FEATURE_INVALID = 0xFFFFFFFF, /* Invalid Feature */
};
enum wifi_logger_feature {
WIFI_LOGGER_MEMORY_DUMP_SUPPORTED = (1 << (0)), // Memory dump of FW
WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED = (1 << (1)), // PKT status
WIFI_LOGGER_CONNECT_EVENT_SUPPORTED = (1 << (2)), // Connectivity event
WIFI_LOGGER_POWER_EVENT_SUPPORTED = (1 << (3)), // POWER of Driver
WIFI_LOGGER_WAKE_LOCK_SUPPORTED = (1 << (4)), // WAKE LOCK of Driver
WIFI_LOGGER_VERBOSE_SUPPORTED = (1 << (5)), // verbose log of FW
WIFI_LOGGER_WATCHDOG_TIMER_SUPPORTED = (1 << (6)), // monitor the health of FW
WIFI_LOGGER_DRIVER_DUMP_SUPPORTED = (1 << (7)), // dumps driver state
WIFI_LOGGER_PACKET_FATE_SUPPORTED = (1 << (8)), // tracks connection packets' fate
};
enum wake_stats_attributes {
WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT,
WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE,
WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT,
WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED,
WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW,
WAKE_STAT_ATTRIBUTE_DRIVER_FW_WAKE,
WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT,
WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT_USED,
WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE,
WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT,
WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT,
WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT,
WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT,
WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT,
WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA,
WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA,
WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS,
WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT,
WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT,
WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT,
WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO,
WAKE_STAT_ATTRIBUTE_AFTER_LAST,
WAKE_STAT_ATTRIBUTE_MAX = WAKE_STAT_ATTRIBUTE_AFTER_LAST - 1,
};
enum vendor_nl80211_subcmd {
/* copied from wpa_supplicant brcm definations */
VENDOR_NL80211_SUBCMD_UNSPEC = 0,
VENDOR_NL80211_SUBCMD_SET_PMK = 4,
VENDOR_NL80211_SUBCMD_SET_MAC = 6,
VENDOR_NL80211_SCMD_ACS = 9,
VENDOR_NL80211_SCMD_MAX = 10,
};
enum nl80211_vendor_subcmd_attributes {
WIFI_VENDOR_ATTR_DRIVER_CMD = 0,
WIFI_VENDOR_ATTR_DRIVER_KEY_PMK = 1,
WIFI_VENDOR_ATTR_DRIVER_MAC_ADDR = 3,
WIFI_VENDOR_ATTR_DRIVER_AFTER_LAST = 5,
WIFI_VENDOR_ATTR_DRIVER_MAX =
WIFI_VENDOR_ATTR_DRIVER_AFTER_LAST - 1,
};
typedef int wifi_ring_buffer_id;
struct wifi_ring_buffer_status {
u8 name[32];
u32 flags;
wifi_ring_buffer_id ring_id;
u32 ring_buffer_byte_size;
u32 verbose_level;
u32 written_bytes;
u32 read_bytes;
u32 written_records;
};
struct rx_data_cnt_details_t {
int rx_unicast_cnt; /*Total rx unicast packet which woke up host */
int rx_multicast_cnt; /*Total rx multicast packet which woke up host */
int rx_broadcast_cnt; /*Total rx broadcast packet which woke up host */
};
struct rx_wake_pkt_type_classification_t {
int icmp_pkt; /*wake icmp packet count */
int icmp6_pkt; /*wake icmp6 packet count */
int icmp6_ra; /*wake icmp6 RA packet count */
int icmp6_na; /*wake icmp6 NA packet count */
int icmp6_ns; /*wake icmp6 NS packet count */
//ToDo: Any more interesting classification to add?
};
struct rx_multicast_cnt_t{
int ipv4_rx_multicast_addr_cnt; /*Rx wake packet was ipv4 multicast */
int ipv6_rx_multicast_addr_cnt; /*Rx wake packet was ipv6 multicast */
int other_rx_multicast_addr_cnt;/*Rx wake packet was non-ipv4 and non-ipv6*/
};
struct wlan_driver_wake_reason_cnt_t {
int total_cmd_event_wake; /* Total count of cmd event wakes */
int *cmd_event_wake_cnt; /* Individual wake count array, each index a reason */
int cmd_event_wake_cnt_sz; /* Max number of cmd event wake reasons */
int cmd_event_wake_cnt_used; /* Number of cmd event wake reasons specific to the driver */
int total_driver_fw_local_wake; /* Total count of drive/fw wakes, for local reasons */
int *driver_fw_local_wake_cnt; /* Individual wake count array, each index a reason */
int driver_fw_local_wake_cnt_sz; /* Max number of local driver/fw wake reasons */
int driver_fw_local_wake_cnt_used; /* Number of local driver/fw wake reasons specific to the driver */
int total_rx_data_wake; /* total data rx packets, that woke up host */
struct rx_data_cnt_details_t rx_wake_details;
struct rx_wake_pkt_type_classification_t rx_wake_pkt_classification_info;
struct rx_multicast_cnt_t rx_multicast_wake_pkt_info;
};
typedef struct wl_mkeep_alive_pkt {
u16 version; /* Version for mkeep_alive */
u16 length; /* length of fixed parameters in the structure */
u32 period_msec; /* high bit on means immediate send */
u16 len_bytes;
u8 keep_alive_id; /* 0 - 3 for N = 4 */
u8 data[1];
} wl_mkeep_alive_pkt_t;
#endif /* _AIC_VENDOR_H */

View File

@@ -0,0 +1,64 @@
#include "rwnx_main.h"
#include "rwnx_msg_tx.h"
#include "reg_access.h"
#include "aicwf_compat_8800d80.h"
#define FW_USERCONFIG_NAME_8800D80 "aic_userconfig_8800d80.txt"
int rwnx_request_firmware_common(struct rwnx_hw *rwnx_hw,
u32** buffer, const char *filename);
void rwnx_plat_userconfig_parsing2(char *buffer, int size);
void rwnx_plat_userconfig_parsing3(char *buffer, int size);
void rwnx_release_firmware_common(u32** buffer);
int aicwf_set_rf_config_8800d80(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm)
{
int ret = 0;
if ((ret = rwnx_send_txpwr_lvl_v3_req(rwnx_hw))) {
return -1;
}
if ((ret = rwnx_send_txpwr_ofst2x_req(rwnx_hw))) {
return -1;
}
if (testmode == 0) {
if ((ret = rwnx_send_rf_calib_req(rwnx_hw, cfm))) {
return -1;
}
}
return 0 ;
}
int rwnx_plat_userconfig_load_8800d80(struct rwnx_hw *rwnx_hw)
{
int size;
u32 *dst=NULL;
char *filename = FW_USERCONFIG_NAME_8800D80;
AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename);
/* load file */
size = rwnx_request_firmware_common(rwnx_hw, &dst, filename);
if (size <= 0) {
AICWFDBG(LOGERROR, "wrong size of firmware file\n");
dst = NULL;
return 0;
}
/* Copy the file on the Embedded side */
AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size);
rwnx_plat_userconfig_parsing3((char *)dst, size);
rwnx_release_firmware_common(&dst);
AICWFDBG(LOGINFO, "userconfig download complete\n\n");
return 0;
}

Some files were not shown because too many files have changed in this diff Show More