mirror of
https://github.com/revyos/thead-kernel.git
synced 2026-06-21 17:22:24 +02:00
Compare commits
13 Commits
merged-ahe
...
update/1.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec72e51306 | ||
|
|
aca5943dcc | ||
|
|
42c464e64e | ||
|
|
b289e7c526 | ||
|
|
0d7d81fcb2 | ||
|
|
71dc346184 | ||
|
|
d6bc7eb396 | ||
|
|
90820cc82a | ||
|
|
d8bd0e5590 | ||
|
|
350bdb61e1 | ||
|
|
e32000fbc0 | ||
|
|
88bd214b7e | ||
|
|
bc48e4fc49 |
72
.github/workflows/kernel.yml
vendored
72
.github/workflows/kernel.yml
vendored
@@ -8,16 +8,16 @@ on:
|
||||
- cron: "0 2 * * *"
|
||||
|
||||
env:
|
||||
xuantie_toolchain: https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1705395627867
|
||||
toolchain_file_name: Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.8.1-20240115.tar.gz
|
||||
mainline_toolchain: https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/2024.03.01
|
||||
mainline_toolchain_file_name: riscv64-glibc-ubuntu-22.04-gcc-nightly-2024.03.01-nightly.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: th1520
|
||||
board: lpi4a
|
||||
KBUILD_BUILD_USER: builder
|
||||
KBUILD_BUILD_HOST: revyos-riscv-builder
|
||||
KDEB_COMPRESS: none
|
||||
KDEB_COMPRESS: xz
|
||||
KDEB_CHANGELOG_DIST: unstable
|
||||
|
||||
jobs:
|
||||
@@ -25,27 +25,22 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: gcc-13
|
||||
cross: riscv64-unknown-linux-gnu-
|
||||
machine: ubuntu-22.04
|
||||
run_image: ghcr.io/revyos/revyos-kernel-builder:amd64-2024.04.02
|
||||
- name: thead-gcc
|
||||
cross: riscv64-unknown-linux-gnu-
|
||||
machine: ubuntu-22.04
|
||||
run_image: ghcr.io/revyos/revyos-kernel-builder:amd64-2024.04.02
|
||||
- name: native
|
||||
cross: riscv64-linux-gnu-
|
||||
machine: [ self-hosted, Linux, riscv64 ]
|
||||
run_image: ghcr.io/revyos/revyos-kernel-builder:riscv64-2024.04.02
|
||||
name: [thead-gcc, gcc-13]
|
||||
board: [lpi4a, ahead]
|
||||
|
||||
runs-on: ${{ matrix.machine }}
|
||||
container:
|
||||
image: ${{ matrix.run_image }}
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
CROSS_COMPILE: ${{ matrix.cross }}
|
||||
CROSS_COMPILE: riscv64-unknown-linux-gnu-
|
||||
|
||||
steps:
|
||||
- name: Install software
|
||||
run: |
|
||||
sudo apt update && \
|
||||
sudo apt install -y gdisk dosfstools g++-12-riscv64-linux-gnu build-essential \
|
||||
libncurses-dev gawk flex bison openssl libssl-dev tree \
|
||||
dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf device-tree-compiler \
|
||||
devscripts pahole
|
||||
|
||||
- name: Checkout kernel
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -57,40 +52,37 @@ jobs:
|
||||
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.1/bin:$PATH"
|
||||
elif [[ ${{ matrix.name }} = "gcc-13" ]]; then
|
||||
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"
|
||||
else
|
||||
echo "No download toolchain."
|
||||
fi
|
||||
${CROSS_COMPILE}gcc -v
|
||||
|
||||
pushd kernel
|
||||
make revyos_defconfig
|
||||
export KDEB_PKGVERSION="$(make kernelversion)-$(date "+%Y.%m.%d.%H.%M")+$(git rev-parse --short HEAD)"
|
||||
if [ x"${{ matrix.board }}" = x"lpi4a" ]; then
|
||||
make revyos_defconfig
|
||||
elif [ x"${{ matrix.board }}" = x"ahead" ]; then
|
||||
make revyos_beaglev_defconfig
|
||||
fi
|
||||
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"
|
||||
if [ `uname -m` = "riscv64" ]; then
|
||||
# FIXME: force use 32 thread
|
||||
make -j32 bindeb-pkg LOCALVERSION="-${board}"
|
||||
else
|
||||
make -j$(nproc) bindeb-pkg LOCALVERSION="-${board}"
|
||||
fi
|
||||
|
||||
make -j$(nproc) bindeb-pkg LOCALVERSION="-${{ matrix.board }}"
|
||||
|
||||
# Copy deb
|
||||
dcmd cp -v ../*.changes ${GITHUB_WORKSPACE}/rootfs/
|
||||
sudo dcmd cp -v ../*.changes ${GITHUB_WORKSPACE}/rootfs/
|
||||
|
||||
# record commit-id
|
||||
git rev-parse HEAD > kernel-commitid
|
||||
cp -v kernel-commitid ${GITHUB_WORKSPACE}/rootfs/
|
||||
git rev-parse HEAD > ${{ matrix.board }}-kernel-commitid
|
||||
sudo cp -v ${{ matrix.board }}-kernel-commitid ${GITHUB_WORKSPACE}/rootfs/
|
||||
|
||||
ls -al ${GITHUB_WORKSPACE}/rootfs/
|
||||
popd
|
||||
|
||||
- name: 'Upload Artifact'
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: thead-kernel-${{ matrix.name }}
|
||||
path: rootfs/*
|
||||
|
||||
@@ -5,8 +5,7 @@ dtbo-$(CONFIG_SOC_THEAD) += \
|
||||
BBORG_RELAY-00A2.dtbo \
|
||||
BONE-LED_P8_03.dtbo \
|
||||
BONE-LED_P9_11.dtbo \
|
||||
BVA-MIKROBUS-0.dtbo \
|
||||
meles-wifibt-external-antenna.dtbo
|
||||
BVA-MIKROBUS-0.dtbo
|
||||
|
||||
targets += dtbs dtbs_install
|
||||
targets += $(dtbo-y)
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
fragment@0 {
|
||||
target-path = "/";
|
||||
|
||||
__overlay__ {
|
||||
ext_antenna: ext-antenna {
|
||||
status = "okay";
|
||||
compatible = "regulator-fixed";
|
||||
enable-active-low;
|
||||
gpio = <&gpio1_porta 24 1>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-name = "ext_antenna";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@1 {
|
||||
target = <&board_antenna>;
|
||||
|
||||
__overlay__ {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
/ {
|
||||
model = "T-HEAD Light Lichee Pi 4A configuration for LicheeConsole4A";
|
||||
compatible = "thead,light", "sipeed,th1520-laptop", "sipeed,console4a";
|
||||
};
|
||||
|
||||
&dsi0_panel0 {
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
/ {
|
||||
model = "T-HEAD Light Lichee Pi 4A configuration for 8GB DDR board use on laptop";
|
||||
compatible = "thead,light", "sipeed,th1520-laptop";
|
||||
|
||||
reg_sys_vcc_5v: regulator-sys-vcc-5v-en {
|
||||
status = "okay";
|
||||
@@ -20,15 +19,12 @@
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
|
||||
// suspend for lichee laptop is not ready so dont turn it off
|
||||
/*
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
regulator-state-standby {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
*/
|
||||
};
|
||||
|
||||
reg_sys_vcc_3v3: regulator-sys-vcc-3v3-en {
|
||||
@@ -119,7 +115,7 @@
|
||||
charger: dc-charger {
|
||||
compatible = "gpio-charger";
|
||||
charger-type = "mains";
|
||||
gpios = <&gpio0_porta 16 GPIO_ACTIVE_HIGH>;
|
||||
gpios = <&ao_gpio_porta 2 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -232,7 +228,6 @@
|
||||
|
||||
&uart3 {
|
||||
clock-frequency = <100000000>;
|
||||
pinctrl-0 = <&pinctrl_uart3_tx_is_gpio>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
@@ -296,10 +296,10 @@
|
||||
debounce-interval = <1>;
|
||||
gpios = <&gpio2_porta 25 0x1>;
|
||||
};
|
||||
key-wake {
|
||||
label = "Wake Key";
|
||||
key-sleep {
|
||||
label = "Sleep Wake Key";
|
||||
wakeup-source;
|
||||
linux,code = <KEY_WAKEUP>;
|
||||
linux,code = <KEY_SLEEP>;
|
||||
debounce-interval = <1>;
|
||||
gpios = <&ao_gpio_porta 2 0x1>;
|
||||
};
|
||||
@@ -1105,16 +1105,6 @@
|
||||
>;
|
||||
};
|
||||
|
||||
|
||||
pinctrl_uart3_tx_is_gpio: uart3txisgpiogrp {
|
||||
thead,pins = <
|
||||
FM_UART3_TXD 0x3 0x202
|
||||
FM_UART3_RXD 0x1 0x202
|
||||
>;
|
||||
};
|
||||
|
||||
|
||||
|
||||
pinctrl_wifi_wake: wifi_grp {
|
||||
thead,pins = <
|
||||
FM_GPIO0_27 0x0 0x202
|
||||
|
||||
@@ -265,36 +265,15 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb_vbus_en: regulator-usb-vbus-en {
|
||||
vcc_usb_en: regulator-usb-en {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "usb_vbus_en";
|
||||
gpio = <&gpio0_porta 27 0>; /* GPIO_ACTIVE_HIGH: 0 */
|
||||
enable-active-high;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* Select USB3.0 Type-A port */
|
||||
usb_select: regulator-usb-select {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "usb_select";
|
||||
regulator-name = "vcc_usb_en";
|
||||
gpio = <&gpio2_porta 30 1>; /* GPIO_ACTIVE_LOW: 1 */
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
board_antenna: board-antenna {
|
||||
status = "okay";
|
||||
compatible = "regulator-fixed";
|
||||
enable-active-high;
|
||||
gpio = <&gpio1_porta 24 0>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-name = "board_antenna";
|
||||
};
|
||||
|
||||
aon {
|
||||
compatible = "thead,light-aon";
|
||||
mbox-names = "aon";
|
||||
|
||||
@@ -1319,6 +1319,7 @@ CONFIG_BT_DEBUGFS=y
|
||||
# CONFIG_BT_HCIBTSDIO is not set
|
||||
CONFIG_BT_HCIUART=y
|
||||
CONFIG_BT_HCIUART_H4=y
|
||||
CONFIG_BT_HCIUART_RTL3WIRE=y
|
||||
# CONFIG_BT_HCIUART_BCSP is not set
|
||||
# CONFIG_BT_HCIUART_ATH3K is not set
|
||||
# CONFIG_BT_HCIUART_INTEL is not set
|
||||
|
||||
1101
arch/riscv/configs/revyos_beaglev_defconfig
Normal file
1101
arch/riscv/configs/revyos_beaglev_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -115,6 +115,14 @@ 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
|
||||
@@ -425,6 +433,4 @@ config BT_HCIRSI
|
||||
Say Y here to compile support for HCI over Redpine into the
|
||||
kernel or say M to compile as a module.
|
||||
|
||||
source "drivers/bluetooth/rtkbt/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -45,6 +45,6 @@ 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)
|
||||
|
||||
obj-$(CONFIG_BT_RTKBT) += rtkbt/
|
||||
|
||||
@@ -654,6 +654,7 @@ 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 },
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
*
|
||||
* Bluetooth HCI UART driver
|
||||
@@ -6,10 +5,25 @@
|
||||
* 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>
|
||||
@@ -17,7 +31,6 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/poll.h>
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/errno.h>
|
||||
@@ -25,18 +38,32 @@
|
||||
#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)
|
||||
{
|
||||
@@ -44,7 +71,7 @@ static int h4_open(struct hci_uart *hu)
|
||||
|
||||
BT_DBG("hu %p", hu);
|
||||
|
||||
h4 = kzalloc(sizeof(*h4), GFP_KERNEL);
|
||||
h4 = kzalloc(sizeof(*h4), GFP_ATOMIC);
|
||||
if (!h4)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -71,6 +98,8 @@ 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);
|
||||
@@ -83,7 +112,7 @@ static int h4_close(struct hci_uart *hu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enqueue frame for transmission (padding, crc, etc) */
|
||||
/* Enqueue frame for transmittion (padding, crc, etc) */
|
||||
static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
|
||||
{
|
||||
struct h4_struct *h4 = hu->priv;
|
||||
@@ -91,34 +120,174 @@ 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), &hci_skb_pkt_type(skb), 1);
|
||||
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
|
||||
skb_queue_tail(&h4->txq, skb);
|
||||
|
||||
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 },
|
||||
};
|
||||
#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;
|
||||
}
|
||||
|
||||
/* Recv data */
|
||||
static int h4_recv(struct hci_uart *hu, const void *data, int count)
|
||||
static int h4_recv(struct hci_uart *hu, 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;
|
||||
|
||||
if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
|
||||
return -EUNATCH;
|
||||
BT_DBG("hu %p count %d rx_state %ld rx_count %ld",
|
||||
hu, count, h4->rx_state, h4->rx_count);
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
return count;
|
||||
@@ -130,9 +299,8 @@ static struct sk_buff *h4_dequeue(struct hci_uart *hu)
|
||||
return skb_dequeue(&h4->txq);
|
||||
}
|
||||
|
||||
static const struct hci_uart_proto h4p = {
|
||||
static struct hci_uart_proto h4p = {
|
||||
.id = HCI_UART_H4,
|
||||
.name = "H4",
|
||||
.open = h4_open,
|
||||
.close = h4_close,
|
||||
.recv = h4_recv,
|
||||
@@ -143,132 +311,17 @@ static const struct hci_uart_proto h4p = {
|
||||
|
||||
int __init h4_init(void)
|
||||
{
|
||||
return hci_uart_register_proto(&h4p);
|
||||
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;
|
||||
}
|
||||
|
||||
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
@@ -1,4 +1,3 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
*
|
||||
* Bluetooth HCI UART driver
|
||||
@@ -6,12 +5,50 @@
|
||||
* 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)
|
||||
@@ -20,7 +57,7 @@
|
||||
#define HCIUARTGETFLAGS _IOR('U', 204, int)
|
||||
|
||||
/* UART protocols */
|
||||
#define HCI_UART_MAX_PROTO 12
|
||||
#define HCI_UART_MAX_PROTO 6
|
||||
|
||||
#define HCI_UART_H4 0
|
||||
#define HCI_UART_BCSP 1
|
||||
@@ -28,12 +65,6 @@
|
||||
#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
|
||||
@@ -43,46 +74,42 @@
|
||||
#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 (*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 (*recv)(struct hci_uart *hu, 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;
|
||||
|
||||
const struct hci_uart_proto *proto;
|
||||
struct percpu_rw_semaphore proto_lock; /* Stop work for proto close */
|
||||
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
|
||||
void *priv;
|
||||
|
||||
struct semaphore tx_sem; /* semaphore for tx */
|
||||
|
||||
struct sk_buff *tx_skb;
|
||||
unsigned long tx_state;
|
||||
|
||||
unsigned int init_speed;
|
||||
unsigned int oper_speed;
|
||||
|
||||
u8 alignment;
|
||||
u8 padding;
|
||||
#if WOBT_NOTIFY
|
||||
struct notifier_block pm_notify_block;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* HCI_UART proto flag bits */
|
||||
@@ -94,108 +121,20 @@ struct hci_uart {
|
||||
#define HCI_UART_SENDING 1
|
||||
#define HCI_UART_TX_WAKEUP 2
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_H4
|
||||
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);
|
||||
extern int h4_init(void);
|
||||
extern int h4_deinit(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_BCSP
|
||||
int bcsp_init(void);
|
||||
int bcsp_deinit(void);
|
||||
#endif
|
||||
extern int h5_init(void);
|
||||
extern int h5_deinit(void);
|
||||
|
||||
#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);
|
||||
#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);
|
||||
#endif
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
config BT_RTKBT
|
||||
tristate "BT_RTKBT"
|
||||
default n
|
||||
help
|
||||
Help message of RTKBT
|
||||
@@ -1,2 +0,0 @@
|
||||
obj-$(CONFIG_BT_RTKBT) := rtkbt.o
|
||||
rtkbt-objs := hci_ldisc.o hci_h4.o hci_rtk_h5.o rtk_coex.o
|
||||
@@ -1,327 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Bluetooth HCI UART driver
|
||||
*
|
||||
* 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>
|
||||
#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 <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)
|
||||
{
|
||||
struct h4_struct *h4;
|
||||
|
||||
BT_DBG("hu %p", hu);
|
||||
|
||||
h4 = kzalloc(sizeof(*h4), GFP_ATOMIC);
|
||||
if (!h4)
|
||||
return -ENOMEM;
|
||||
|
||||
skb_queue_head_init(&h4->txq);
|
||||
|
||||
hu->priv = h4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Flush protocol data */
|
||||
static int h4_flush(struct hci_uart *hu)
|
||||
{
|
||||
struct h4_struct *h4 = hu->priv;
|
||||
|
||||
BT_DBG("hu %p", hu);
|
||||
|
||||
skb_queue_purge(&h4->txq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Close protocol */
|
||||
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);
|
||||
|
||||
kfree_skb(h4->rx_skb);
|
||||
|
||||
hu->priv = NULL;
|
||||
kfree(h4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enqueue frame for transmittion (padding, crc, etc) */
|
||||
static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
|
||||
{
|
||||
struct h4_struct *h4 = hu->priv;
|
||||
|
||||
BT_DBG("hu %p skb %p", hu, skb);
|
||||
|
||||
/* Prepend skb with frame type */
|
||||
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 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;
|
||||
}
|
||||
|
||||
/* Recv data */
|
||||
static int h4_recv(struct hci_uart *hu, 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct sk_buff *h4_dequeue(struct hci_uart *hu)
|
||||
{
|
||||
struct h4_struct *h4 = hu->priv;
|
||||
return skb_dequeue(&h4->txq);
|
||||
}
|
||||
|
||||
static struct hci_uart_proto h4p = {
|
||||
.id = HCI_UART_H4,
|
||||
.open = h4_open,
|
||||
.close = h4_close,
|
||||
.recv = h4_recv,
|
||||
.enqueue = h4_enqueue,
|
||||
.dequeue = h4_dequeue,
|
||||
.flush = h4_flush,
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int __exit h4_deinit(void)
|
||||
{
|
||||
return hci_uart_unregister_proto(&h4p);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Bluetooth HCI UART driver
|
||||
*
|
||||
* 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 */
|
||||
|
||||
/* RTKBT Power-on Data Filter for Manufacturer field */
|
||||
/* Note that please edit the datafilter in
|
||||
* rtkbt_set_le_device_poweron_data_filter() of hci_ldisc.c */
|
||||
#define RTKBT_TV_POWERON_DATA_FILTER (0 * WOBT_NOTIFY) /* 1 enable; 0 disable */
|
||||
|
||||
/* Ioctls */
|
||||
#define HCIUARTSETPROTO _IOW('U', 200, int)
|
||||
#define HCIUARTGETPROTO _IOR('U', 201, int)
|
||||
#define HCIUARTGETDEVICE _IOR('U', 202, int)
|
||||
#define HCIUARTSETFLAGS _IOW('U', 203, int)
|
||||
#define HCIUARTGETFLAGS _IOR('U', 204, int)
|
||||
|
||||
/* UART protocols */
|
||||
#define HCI_UART_MAX_PROTO 6
|
||||
|
||||
#define HCI_UART_H4 0
|
||||
#define HCI_UART_BCSP 1
|
||||
#define HCI_UART_3WIRE 2
|
||||
#define HCI_UART_H4DS 3
|
||||
#define HCI_UART_LL 4
|
||||
#define HCI_UART_ATH3K 5
|
||||
|
||||
#define HCI_UART_RAW_DEVICE 0
|
||||
#define HCI_UART_RESET_ON_INIT 1
|
||||
#define HCI_UART_CREATE_AMP 2
|
||||
#define HCI_UART_INIT_PENDING 3
|
||||
#define HCI_UART_EXT_CONFIG 4
|
||||
#define HCI_UART_VND_DETECT 5
|
||||
|
||||
struct hci_uart;
|
||||
|
||||
struct hci_uart_proto {
|
||||
unsigned int id;
|
||||
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 (*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 hci_dev *hdev;
|
||||
unsigned long flags;
|
||||
unsigned long hdev_flags;
|
||||
|
||||
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
|
||||
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
|
||||
};
|
||||
|
||||
/* HCI_UART proto flag bits */
|
||||
#define HCI_UART_PROTO_SET 0
|
||||
#define HCI_UART_REGISTERED 1
|
||||
#define HCI_UART_PROTO_READY 2
|
||||
|
||||
/* TX states */
|
||||
#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);
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_H4
|
||||
extern int h4_init(void);
|
||||
extern int h4_deinit(void);
|
||||
#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);
|
||||
#endif
|
||||
@@ -148,6 +148,7 @@
|
||||
#define PVRSRV_RGX_LOG2_CLIENT_CCB_MAX_SIZE_TDM 17
|
||||
#define PVRSRV_RGX_LOG2_CLIENT_CCB_MAX_SIZE_RDM 15
|
||||
#define SUPPORT_BUFFER_SYNC 1
|
||||
#define SUPPORT_LINUX_DVFS 1
|
||||
#ifdef CONFIG_DRM_POWERVR_ROGUE_DEBUG
|
||||
#define DEBUG
|
||||
#define DEBUG_BRIDGE_KM
|
||||
|
||||
@@ -43,6 +43,7 @@ override SUPPORT_DI_BRG_IMPL := 1
|
||||
override SUPPORT_NATIVE_FENCE_SYNC := 1
|
||||
override SUPPORT_DMA_FENCE := 1
|
||||
override SUPPORT_BUFFER_SYNC := 1
|
||||
override SUPPORT_LINUX_DVFS := 1
|
||||
ifeq ($(CONFIG_DRM_POWERVR_ROGUE_DEBUG),y)
|
||||
override BUILD := debug
|
||||
override PVRSRV_ENABLE_GPU_MEMORY_INFO := 1
|
||||
|
||||
138
drivers/gpu/drm/img-rogue/pvr_dvfs.h
Normal file
138
drivers/gpu/drm/img-rogue/pvr_dvfs.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/*************************************************************************/ /*!
|
||||
@File pvr_dvfs.h
|
||||
@Title System level interface for DVFS
|
||||
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
|
||||
@License Dual MIT/GPLv2
|
||||
|
||||
The contents of this file are subject to the MIT license as set out below.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
the GNU General Public License Version 2 ("GPL") in which case the provisions
|
||||
of GPL are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
GPL, and not to allow others to use your version of this file under the terms
|
||||
of the MIT license, indicate your decision by deleting the provisions above
|
||||
and replace them with the notice and other provisions required by GPL as set
|
||||
out in the file called "GPL-COPYING" included in this distribution. If you do
|
||||
not delete the provisions above, a recipient may use your version of this file
|
||||
under the terms of either the MIT license or GPL.
|
||||
|
||||
This License is also included in this distribution in the file called
|
||||
"MIT-COPYING".
|
||||
|
||||
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
|
||||
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/ /**************************************************************************/
|
||||
|
||||
#ifndef PVR_DVFS_H
|
||||
#define PVR_DVFS_H
|
||||
|
||||
#include <linux/version.h>
|
||||
|
||||
#if defined(SUPPORT_LINUX_DVFS)
|
||||
#include <linux/devfreq.h>
|
||||
#include <linux/thermal.h>
|
||||
|
||||
#if defined(CONFIG_DEVFREQ_THERMAL)
|
||||
#include <linux/devfreq_cooling.h>
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
|
||||
#include <linux/opp.h>
|
||||
#else
|
||||
#include <linux/pm_opp.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "img_types.h"
|
||||
|
||||
typedef void (*PFN_SYS_DEV_DVFS_SET_FREQUENCY)(IMG_UINT32 ui32Freq);
|
||||
typedef void (*PFN_SYS_DEV_DVFS_SET_VOLTAGE)(IMG_UINT32 ui32Volt);
|
||||
|
||||
typedef struct _IMG_OPP_
|
||||
{
|
||||
IMG_UINT32 ui32Volt;
|
||||
/*
|
||||
* Unit of frequency in Hz.
|
||||
*/
|
||||
IMG_UINT32 ui32Freq;
|
||||
} IMG_OPP;
|
||||
|
||||
typedef struct _IMG_DVFS_DEVICE_CFG_
|
||||
{
|
||||
const IMG_OPP *pasOPPTable;
|
||||
IMG_UINT32 ui32OPPTableSize;
|
||||
#if defined(SUPPORT_LINUX_DVFS)
|
||||
IMG_UINT32 ui32PollMs;
|
||||
#endif
|
||||
IMG_BOOL bIdleReq;
|
||||
PFN_SYS_DEV_DVFS_SET_FREQUENCY pfnSetFrequency;
|
||||
PFN_SYS_DEV_DVFS_SET_VOLTAGE pfnSetVoltage;
|
||||
|
||||
#if defined(CONFIG_DEVFREQ_THERMAL) && defined(SUPPORT_LINUX_DVFS)
|
||||
struct devfreq_cooling_power *psPowerOps;
|
||||
#endif
|
||||
} IMG_DVFS_DEVICE_CFG;
|
||||
|
||||
#if defined(SUPPORT_LINUX_DVFS)
|
||||
typedef struct _IMG_DVFS_GOVERNOR_
|
||||
{
|
||||
IMG_BOOL bEnabled;
|
||||
} IMG_DVFS_GOVERNOR;
|
||||
|
||||
typedef struct _IMG_DVFS_GOVERNOR_CFG_
|
||||
{
|
||||
IMG_UINT32 ui32UpThreshold;
|
||||
IMG_UINT32 ui32DownDifferential;
|
||||
} IMG_DVFS_GOVERNOR_CFG;
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
#if defined(SUPPORT_LINUX_DVFS)
|
||||
typedef struct _IMG_DVFS_DEVICE_
|
||||
{
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
|
||||
struct opp *psOPP;
|
||||
#else
|
||||
struct dev_pm_opp *psOPP;
|
||||
#endif
|
||||
struct devfreq *psDevFreq;
|
||||
IMG_BOOL bInitPending;
|
||||
IMG_BOOL bReady;
|
||||
IMG_BOOL bEnabled;
|
||||
IMG_HANDLE hGpuUtilUserDVFS;
|
||||
struct devfreq_simple_ondemand_data data;
|
||||
#if defined(CONFIG_DEVFREQ_THERMAL)
|
||||
struct thermal_cooling_device *psDevfreqCoolingDevice;
|
||||
#endif
|
||||
} IMG_DVFS_DEVICE;
|
||||
#endif
|
||||
|
||||
typedef struct _IMG_DVFS_
|
||||
{
|
||||
#if defined(SUPPORT_LINUX_DVFS)
|
||||
IMG_DVFS_DEVICE sDVFSDevice;
|
||||
IMG_DVFS_GOVERNOR sDVFSGovernor;
|
||||
IMG_DVFS_GOVERNOR_CFG sDVFSGovernorCfg;
|
||||
#endif
|
||||
IMG_DVFS_DEVICE_CFG sDVFSDeviceCfg;
|
||||
} PVRSRV_DVFS;
|
||||
#endif/* (__linux__) */
|
||||
|
||||
#endif /* PVR_DVFS_H */
|
||||
824
drivers/gpu/drm/img-rogue/pvr_dvfs_device.c
Normal file
824
drivers/gpu/drm/img-rogue/pvr_dvfs_device.c
Normal file
@@ -0,0 +1,824 @@
|
||||
/*************************************************************************/ /*!
|
||||
@File
|
||||
@Title PowerVR devfreq device implementation
|
||||
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
|
||||
@Description Linux module setup
|
||||
@License Dual MIT/GPLv2
|
||||
|
||||
The contents of this file are subject to the MIT license as set out below.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
the GNU General Public License Version 2 ("GPL") in which case the provisions
|
||||
of GPL are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
GPL, and not to allow others to use your version of this file under the terms
|
||||
of the MIT license, indicate your decision by deleting the provisions above
|
||||
and replace them with the notice and other provisions required by GPL as set
|
||||
out in the file called "GPL-COPYING" included in this distribution. If you do
|
||||
not delete the provisions above, a recipient may use your version of this file
|
||||
under the terms of either the MIT license or GPL.
|
||||
|
||||
This License is also included in this distribution in the file called
|
||||
"MIT-COPYING".
|
||||
|
||||
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
|
||||
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/ /**************************************************************************/
|
||||
|
||||
#if !defined(NO_HARDWARE)
|
||||
|
||||
#include <linux/devfreq.h>
|
||||
#if defined(CONFIG_DEVFREQ_THERMAL)
|
||||
#include <linux/devfreq_cooling.h>
|
||||
#endif
|
||||
#include <linux/version.h>
|
||||
#include <linux/device.h>
|
||||
#include <drm/drm.h>
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0))
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_file.h>
|
||||
#else
|
||||
#include <drm/drmP.h>
|
||||
#endif
|
||||
|
||||
#include "power.h"
|
||||
#include "pvrsrv.h"
|
||||
#include "pvrsrv_device.h"
|
||||
|
||||
#include "rgxdevice.h"
|
||||
#include "rgxinit.h"
|
||||
#include "sofunc_rgx.h"
|
||||
|
||||
#include "syscommon.h"
|
||||
|
||||
#include "pvr_dvfs_device.h"
|
||||
|
||||
#include "kernel_compatibility.h"
|
||||
|
||||
static int _device_get_devid(struct device *dev)
|
||||
{
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
int deviceId;
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0))
|
||||
/*
|
||||
* Older kernels do not have render drm_minor member in drm_device,
|
||||
* so we fallback to primary node for device identification
|
||||
*/
|
||||
deviceId = ddev->primary->index;
|
||||
#else
|
||||
if (ddev->render)
|
||||
deviceId = ddev->render->index;
|
||||
else /* when render node is NULL, fallback to primary node */
|
||||
deviceId = ddev->primary->index;
|
||||
#endif
|
||||
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
static IMG_INT32 devfreq_target(struct device *dev, unsigned long *requested_freq, IMG_UINT32 flags)
|
||||
{
|
||||
int deviceId = _device_get_devid(dev);
|
||||
PVRSRV_DEVICE_NODE *psDeviceNode = PVRSRVGetDeviceInstanceByOSId(deviceId);
|
||||
RGX_DATA *psRGXData = NULL;
|
||||
IMG_DVFS_DEVICE *psDVFSDevice = NULL;
|
||||
IMG_DVFS_DEVICE_CFG *psDVFSDeviceCfg = NULL;
|
||||
RGX_TIMING_INFORMATION *psRGXTimingInfo = NULL;
|
||||
IMG_UINT32 ui32Freq, ui32CurFreq, ui32Volt;
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
|
||||
struct opp *opp;
|
||||
#else
|
||||
struct dev_pm_opp *opp;
|
||||
#endif
|
||||
|
||||
/* Check the device is registered */
|
||||
if (!psDeviceNode)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
|
||||
psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
|
||||
psDVFSDeviceCfg = &psDeviceNode->psDevConfig->sDVFS.sDVFSDeviceCfg;
|
||||
|
||||
/* Check the RGX device is initialised */
|
||||
if (!psRGXData)
|
||||
{
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
psRGXTimingInfo = psRGXData->psRGXTimingInfo;
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0))
|
||||
rcu_read_lock();
|
||||
#endif
|
||||
|
||||
opp = devfreq_recommended_opp(dev, requested_freq, flags);
|
||||
if (IS_ERR(opp)) {
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0))
|
||||
rcu_read_unlock();
|
||||
#endif
|
||||
PVR_DPF((PVR_DBG_ERROR, "Invalid OPP"));
|
||||
return PTR_ERR(opp);
|
||||
}
|
||||
|
||||
ui32Freq = dev_pm_opp_get_freq(opp);
|
||||
ui32Volt = dev_pm_opp_get_voltage(opp);
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0))
|
||||
rcu_read_unlock();
|
||||
#else
|
||||
dev_pm_opp_put(opp);
|
||||
#endif
|
||||
|
||||
ui32CurFreq = psRGXTimingInfo->ui32CoreClockSpeed;
|
||||
|
||||
if (ui32CurFreq == ui32Freq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (psDeviceNode->eCurrentSysPowerState != PVRSRV_SYS_POWER_STATE_ON)
|
||||
{
|
||||
*requested_freq = psRGXTimingInfo->ui32CoreClockSpeed;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (PVRSRV_OK != PVRSRVDevicePreClockSpeedChange(psDeviceNode,
|
||||
psDVFSDeviceCfg->bIdleReq,
|
||||
NULL))
|
||||
{
|
||||
dev_err(dev, "PVRSRVDevicePreClockSpeedChange failed\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (!psDVFSDevice->bEnabled)
|
||||
{
|
||||
*requested_freq = psRGXTimingInfo->ui32CoreClockSpeed;
|
||||
goto ClockSpeedChangePost;
|
||||
}
|
||||
|
||||
/* Increasing frequency, change voltage first */
|
||||
if (ui32Freq > ui32CurFreq)
|
||||
{
|
||||
psDVFSDeviceCfg->pfnSetVoltage(ui32Volt);
|
||||
}
|
||||
|
||||
psDVFSDeviceCfg->pfnSetFrequency(ui32Freq);
|
||||
|
||||
/* Decreasing frequency, change frequency first */
|
||||
if (ui32Freq < ui32CurFreq)
|
||||
{
|
||||
psDVFSDeviceCfg->pfnSetVoltage(ui32Volt);
|
||||
}
|
||||
|
||||
psRGXTimingInfo->ui32CoreClockSpeed = ui32Freq;
|
||||
|
||||
ClockSpeedChangePost:
|
||||
PVRSRVDevicePostClockSpeedChange(psDeviceNode, psDVFSDeviceCfg->bIdleReq,
|
||||
NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int devfreq_get_dev_status(struct device *dev, struct devfreq_dev_status *stat)
|
||||
{
|
||||
int deviceId = _device_get_devid(dev);
|
||||
PVRSRV_DEVICE_NODE *psDeviceNode = PVRSRVGetDeviceInstanceByOSId(deviceId);
|
||||
PVRSRV_RGXDEV_INFO *psDevInfo = NULL;
|
||||
IMG_DVFS_DEVICE *psDVFSDevice = NULL;
|
||||
RGX_DATA *psRGXData = NULL;
|
||||
RGX_TIMING_INFORMATION *psRGXTimingInfo = NULL;
|
||||
RGXFWIF_GPU_UTIL_STATS sGpuUtilStats;
|
||||
PVRSRV_ERROR eError;
|
||||
|
||||
/* Check the device is registered */
|
||||
if (!psDeviceNode)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
psDevInfo = psDeviceNode->pvDevice;
|
||||
psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
|
||||
psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
|
||||
|
||||
/* Check the RGX device is initialised */
|
||||
if (!psDevInfo || !psRGXData)
|
||||
{
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
psRGXTimingInfo = psRGXData->psRGXTimingInfo;
|
||||
stat->current_frequency = psRGXTimingInfo->ui32CoreClockSpeed;
|
||||
|
||||
if (psDevInfo->pfnGetGpuUtilStats == NULL)
|
||||
{
|
||||
/* Not yet ready. So set times to something sensible. */
|
||||
stat->busy_time = 0;
|
||||
stat->total_time = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
eError = psDevInfo->pfnGetGpuUtilStats(psDeviceNode,
|
||||
psDVFSDevice->hGpuUtilUserDVFS,
|
||||
&sGpuUtilStats);
|
||||
|
||||
if (eError != PVRSRV_OK)
|
||||
{
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
stat->busy_time = sGpuUtilStats.ui64GpuStatActive;
|
||||
stat->total_time = sGpuUtilStats.ui64GpuStatCumulative;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
|
||||
static IMG_INT32 devfreq_cur_freq(struct device *dev, unsigned long *freq)
|
||||
{
|
||||
int deviceId = _device_get_devid(dev);
|
||||
PVRSRV_DEVICE_NODE *psDeviceNode = PVRSRVGetDeviceInstanceByOSId(deviceId);
|
||||
RGX_DATA *psRGXData = NULL;
|
||||
|
||||
/* Check the device is registered */
|
||||
if (!psDeviceNode)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
|
||||
|
||||
/* Check the RGX device is initialised */
|
||||
if (!psRGXData)
|
||||
{
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
*freq = psRGXData->psRGXTimingInfo->ui32CoreClockSpeed;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct devfreq_dev_profile img_devfreq_dev_profile =
|
||||
{
|
||||
.target = devfreq_target,
|
||||
.get_dev_status = devfreq_get_dev_status,
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
|
||||
.get_cur_freq = devfreq_cur_freq,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int FillOPPTable(struct device *dev, PVRSRV_DEVICE_NODE *psDeviceNode)
|
||||
{
|
||||
const IMG_OPP *iopp;
|
||||
int i, err = 0;
|
||||
IMG_DVFS_DEVICE_CFG *psDVFSDeviceCfg = NULL;
|
||||
|
||||
/* Check the device exists */
|
||||
if (!dev || !psDeviceNode)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
psDVFSDeviceCfg = &psDeviceNode->psDevConfig->sDVFS.sDVFSDeviceCfg;
|
||||
|
||||
for (i = 0, iopp = psDVFSDeviceCfg->pasOPPTable;
|
||||
i < psDVFSDeviceCfg->ui32OPPTableSize;
|
||||
i++, iopp++)
|
||||
{
|
||||
err = dev_pm_opp_add(dev, iopp->ui32Freq, iopp->ui32Volt);
|
||||
if (err) {
|
||||
dev_err(dev, "Could not add OPP entry, %d\n", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ClearOPPTable(struct device *dev, PVRSRV_DEVICE_NODE *psDeviceNode)
|
||||
{
|
||||
#if (defined(CHROMIUMOS_KERNEL) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))) || \
|
||||
(LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
|
||||
const IMG_OPP *iopp;
|
||||
int i;
|
||||
IMG_DVFS_DEVICE_CFG *psDVFSDeviceCfg = NULL;
|
||||
|
||||
/* Check the device exists */
|
||||
if (!dev || !psDeviceNode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
psDVFSDeviceCfg = &psDeviceNode->psDevConfig->sDVFS.sDVFSDeviceCfg;
|
||||
|
||||
for (i = 0, iopp = psDVFSDeviceCfg->pasOPPTable;
|
||||
i < psDVFSDeviceCfg->ui32OPPTableSize;
|
||||
i++, iopp++)
|
||||
{
|
||||
dev_pm_opp_remove(dev, iopp->ui32Freq);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int GetOPPValues(struct device *dev,
|
||||
unsigned long *min_freq,
|
||||
unsigned long *min_volt,
|
||||
unsigned long *max_freq)
|
||||
{
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
|
||||
struct opp *opp;
|
||||
#else
|
||||
struct dev_pm_opp *opp;
|
||||
#endif
|
||||
int count, i, err = 0;
|
||||
unsigned long freq;
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)) && \
|
||||
(!defined(CHROMIUMOS_KERNEL) || (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
|
||||
unsigned int *freq_table;
|
||||
#else
|
||||
unsigned long *freq_table;
|
||||
#endif
|
||||
|
||||
count = dev_pm_opp_get_opp_count(dev);
|
||||
if (count < 0)
|
||||
{
|
||||
dev_err(dev, "Could not fetch OPP count, %d\n", count);
|
||||
return count;
|
||||
}
|
||||
|
||||
dev_info(dev, "Found %d OPP points.\n", count);
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
|
||||
freq_table = devm_kcalloc(dev, count, sizeof(*freq_table), GFP_ATOMIC);
|
||||
#else
|
||||
freq_table = kcalloc(count, sizeof(*freq_table), GFP_ATOMIC);
|
||||
#endif
|
||||
if (! freq_table)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0))
|
||||
/* Start RCU read-side critical section to map frequency to OPP */
|
||||
rcu_read_lock();
|
||||
#endif
|
||||
|
||||
/* Iterate over OPP table; Iteration 0 finds "opp w/ freq >= 0 Hz". */
|
||||
freq = 0;
|
||||
opp = dev_pm_opp_find_freq_ceil(dev, &freq);
|
||||
if (IS_ERR(opp))
|
||||
{
|
||||
err = PTR_ERR(opp);
|
||||
dev_err(dev, "Couldn't find lowest frequency, %d\n", err);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
*min_volt = dev_pm_opp_get_voltage(opp);
|
||||
*max_freq = *min_freq = freq_table[0] = freq;
|
||||
dev_info(dev, "opp[%d/%d]: (%lu Hz, %lu uV)\n", 1, count, freq, *min_volt);
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
|
||||
dev_pm_opp_put(opp);
|
||||
#endif
|
||||
|
||||
/* Iteration i > 0 finds "opp w/ freq >= (opp[i-1].freq + 1)". */
|
||||
for (i = 1; i < count; i++)
|
||||
{
|
||||
freq++;
|
||||
opp = dev_pm_opp_find_freq_ceil(dev, &freq);
|
||||
if (IS_ERR(opp))
|
||||
{
|
||||
err = PTR_ERR(opp);
|
||||
dev_err(dev, "Couldn't find %dth frequency, %d\n", i, err);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
freq_table[i] = freq;
|
||||
*max_freq = freq;
|
||||
dev_info(dev,
|
||||
"opp[%d/%d]: (%lu Hz, %lu uV)\n",
|
||||
i + 1,
|
||||
count,
|
||||
freq,
|
||||
dev_pm_opp_get_voltage(opp));
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
|
||||
dev_pm_opp_put(opp);
|
||||
#endif
|
||||
}
|
||||
|
||||
exit:
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0))
|
||||
rcu_read_unlock();
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
|
||||
if (!err)
|
||||
{
|
||||
img_devfreq_dev_profile.freq_table = freq_table;
|
||||
img_devfreq_dev_profile.max_state = count;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
|
||||
devm_kfree(dev, freq_table);
|
||||
#else
|
||||
kfree(freq_table);
|
||||
#endif
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEVFREQ_THERMAL)
|
||||
static int RegisterCoolingDevice(struct device *dev,
|
||||
IMG_DVFS_DEVICE *psDVFSDevice,
|
||||
struct devfreq_cooling_power *powerOps)
|
||||
{
|
||||
struct device_node *of_node;
|
||||
int err = 0;
|
||||
PVRSRV_VZ_RET_IF_MODE(GUEST, err);
|
||||
|
||||
if (!psDVFSDevice)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!powerOps)
|
||||
{
|
||||
dev_info(dev, "Cooling: power ops not registered, not enabling cooling");
|
||||
return 0;
|
||||
}
|
||||
|
||||
of_node = of_node_get(dev->of_node);
|
||||
|
||||
psDVFSDevice->psDevfreqCoolingDevice = of_devfreq_cooling_register_power(
|
||||
of_node, psDVFSDevice->psDevFreq, powerOps);
|
||||
|
||||
if (IS_ERR(psDVFSDevice->psDevfreqCoolingDevice))
|
||||
{
|
||||
err = PTR_ERR(psDVFSDevice->psDevfreqCoolingDevice);
|
||||
dev_err(dev, "Failed to register as devfreq cooling device %d", err);
|
||||
}
|
||||
|
||||
of_node_put(of_node);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define TO_IMG_ERR(err) ((err == -EPROBE_DEFER) ? PVRSRV_ERROR_PROBE_DEFER : PVRSRV_ERROR_INIT_FAILURE)
|
||||
|
||||
PVRSRV_ERROR InitDVFS(PPVRSRV_DEVICE_NODE psDeviceNode)
|
||||
{
|
||||
IMG_DVFS_DEVICE *psDVFSDevice = NULL;
|
||||
IMG_DVFS_DEVICE_CFG *psDVFSDeviceCfg = NULL;
|
||||
struct device *psDev;
|
||||
PVRSRV_ERROR eError;
|
||||
int err;
|
||||
|
||||
PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
|
||||
|
||||
#if !defined(CONFIG_PM_OPP)
|
||||
return PVRSRV_ERROR_NOT_SUPPORTED;
|
||||
#endif
|
||||
|
||||
if (!psDeviceNode)
|
||||
{
|
||||
return PVRSRV_ERROR_INVALID_PARAMS;
|
||||
}
|
||||
|
||||
if (psDeviceNode->psDevConfig->sDVFS.sDVFSDevice.bInitPending)
|
||||
{
|
||||
PVR_DPF((PVR_DBG_ERROR,
|
||||
"DVFS initialise pending for device node %p",
|
||||
psDeviceNode));
|
||||
return PVRSRV_ERROR_INIT_FAILURE;
|
||||
}
|
||||
|
||||
psDev = psDeviceNode->psDevConfig->pvOSDevice;
|
||||
psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
|
||||
psDVFSDeviceCfg = &psDeviceNode->psDevConfig->sDVFS.sDVFSDeviceCfg;
|
||||
psDeviceNode->psDevConfig->sDVFS.sDVFSDevice.bInitPending = IMG_TRUE;
|
||||
|
||||
#if defined(SUPPORT_SOC_TIMER)
|
||||
if (! psDeviceNode->psDevConfig->pfnSoCTimerRead)
|
||||
{
|
||||
PVR_DPF((PVR_DBG_ERROR, "System layer SoC timer callback not implemented"));
|
||||
return PVRSRV_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
eError = SORgxGpuUtilStatsRegister(&psDVFSDevice->hGpuUtilUserDVFS);
|
||||
if (eError != PVRSRV_OK)
|
||||
{
|
||||
PVR_DPF((PVR_DBG_ERROR, "Failed to register to the GPU utilisation stats, %d", eError));
|
||||
return eError;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
err = dev_pm_opp_of_add_table(psDev);
|
||||
if (err)
|
||||
{
|
||||
/*
|
||||
* If there are no device tree or system layer provided operating points
|
||||
* then return an error
|
||||
*/
|
||||
if (err != -ENODEV || !psDVFSDeviceCfg->pasOPPTable)
|
||||
{
|
||||
PVR_DPF((PVR_DBG_ERROR, "Failed to init opp table from devicetree, %d", err));
|
||||
eError = TO_IMG_ERR(err);
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (psDVFSDeviceCfg->pasOPPTable)
|
||||
{
|
||||
err = FillOPPTable(psDev, psDeviceNode);
|
||||
if (err)
|
||||
{
|
||||
PVR_DPF((PVR_DBG_ERROR, "Failed to fill OPP table with data, %d", err));
|
||||
eError = TO_IMG_ERR(err);
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
|
||||
PVR_TRACE(("PVR DVFS init pending: dev = %p, PVR device = %p",
|
||||
psDev, psDeviceNode));
|
||||
|
||||
return PVRSRV_OK;
|
||||
|
||||
err_exit:
|
||||
DeinitDVFS(psDeviceNode);
|
||||
return eError;
|
||||
}
|
||||
|
||||
PVRSRV_ERROR RegisterDVFSDevice(PPVRSRV_DEVICE_NODE psDeviceNode)
|
||||
{
|
||||
IMG_DVFS_DEVICE *psDVFSDevice = NULL;
|
||||
IMG_DVFS_DEVICE_CFG *psDVFSDeviceCfg = NULL;
|
||||
IMG_DVFS_GOVERNOR_CFG *psDVFSGovernorCfg = NULL;
|
||||
RGX_TIMING_INFORMATION *psRGXTimingInfo = NULL;
|
||||
struct device *psDev;
|
||||
unsigned long min_freq = 0, max_freq = 0, min_volt = 0;
|
||||
PVRSRV_ERROR eError;
|
||||
int err;
|
||||
|
||||
if (!psDeviceNode)
|
||||
{
|
||||
return PVRSRV_ERROR_INVALID_PARAMS;
|
||||
}
|
||||
|
||||
if (!psDeviceNode->psDevConfig->sDVFS.sDVFSDevice.bInitPending)
|
||||
{
|
||||
PVR_DPF((PVR_DBG_ERROR,
|
||||
"DVFS initialise not yet pending for device node %p",
|
||||
psDeviceNode));
|
||||
return PVRSRV_ERROR_INIT_FAILURE;
|
||||
}
|
||||
|
||||
psDev = psDeviceNode->psDevConfig->pvOSDevice;
|
||||
psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
|
||||
psDVFSDeviceCfg = &psDeviceNode->psDevConfig->sDVFS.sDVFSDeviceCfg;
|
||||
psDVFSGovernorCfg = &psDeviceNode->psDevConfig->sDVFS.sDVFSGovernorCfg;
|
||||
psRGXTimingInfo = ((RGX_DATA *)psDeviceNode->psDevConfig->hDevData)->psRGXTimingInfo;
|
||||
psDeviceNode->psDevConfig->sDVFS.sDVFSDevice.bInitPending = IMG_FALSE;
|
||||
psDeviceNode->psDevConfig->sDVFS.sDVFSDevice.bReady = IMG_TRUE;
|
||||
|
||||
err = GetOPPValues(psDev, &min_freq, &min_volt, &max_freq);
|
||||
if (err)
|
||||
{
|
||||
PVR_DPF((PVR_DBG_ERROR, "Failed to read OPP points, %d", err));
|
||||
eError = TO_IMG_ERR(err);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
img_devfreq_dev_profile.initial_freq = min_freq;
|
||||
img_devfreq_dev_profile.polling_ms = psDVFSDeviceCfg->ui32PollMs;
|
||||
|
||||
psRGXTimingInfo->ui32CoreClockSpeed = min_freq;
|
||||
|
||||
psDVFSDeviceCfg->pfnSetFrequency(min_freq);
|
||||
psDVFSDeviceCfg->pfnSetVoltage(min_volt);
|
||||
|
||||
psDVFSDevice->data.upthreshold = psDVFSGovernorCfg->ui32UpThreshold;
|
||||
psDVFSDevice->data.downdifferential = psDVFSGovernorCfg->ui32DownDifferential;
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
|
||||
psDVFSDevice->psDevFreq = devm_devfreq_add_device(psDev,
|
||||
&img_devfreq_dev_profile,
|
||||
"simple_ondemand",
|
||||
&psDVFSDevice->data);
|
||||
#else
|
||||
psDVFSDevice->psDevFreq = devfreq_add_device(psDev,
|
||||
&img_devfreq_dev_profile,
|
||||
"simple_ondemand",
|
||||
&psDVFSDevice->data);
|
||||
#endif
|
||||
|
||||
if (IS_ERR(psDVFSDevice->psDevFreq))
|
||||
{
|
||||
PVR_DPF((PVR_DBG_ERROR,
|
||||
"Failed to add as devfreq device %p, %ld",
|
||||
psDVFSDevice->psDevFreq,
|
||||
PTR_ERR(psDVFSDevice->psDevFreq)));
|
||||
eError = TO_IMG_ERR(PTR_ERR(psDVFSDevice->psDevFreq));
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
eError = SuspendDVFS(psDeviceNode);
|
||||
if (eError != PVRSRV_OK)
|
||||
{
|
||||
PVR_DPF((PVR_DBG_ERROR, "PVRSRVInit: Failed to suspend DVFS"));
|
||||
goto err_exit;
|
||||
}
|
||||
err = devfreq_suspend_device(psDVFSDevice->psDevFreq);
|
||||
if (err < 0)
|
||||
{
|
||||
PVR_DPF((PVR_DBG_ERROR, "failed to suspend the devfreq devices"));
|
||||
eError = TO_IMG_ERR(err);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
#if defined(CHROMIUMOS_KERNEL) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0))
|
||||
psDVFSDevice->psDevFreq->policy.user.min_freq = min_freq;
|
||||
psDVFSDevice->psDevFreq->policy.user.max_freq = max_freq;
|
||||
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0))
|
||||
psDVFSDevice->psDevFreq->scaling_min_freq = min_freq;
|
||||
psDVFSDevice->psDevFreq->scaling_max_freq = max_freq;
|
||||
#else
|
||||
psDVFSDevice->psDevFreq->min_freq = min_freq;
|
||||
psDVFSDevice->psDevFreq->max_freq = max_freq;
|
||||
#endif
|
||||
|
||||
err = devfreq_register_opp_notifier(psDev, psDVFSDevice->psDevFreq);
|
||||
if (err)
|
||||
{
|
||||
PVR_DPF((PVR_DBG_ERROR, "Failed to register opp notifier, %d", err));
|
||||
eError = TO_IMG_ERR(err);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEVFREQ_THERMAL)
|
||||
err = RegisterCoolingDevice(psDev, psDVFSDevice, psDVFSDeviceCfg->psPowerOps);
|
||||
if (err)
|
||||
{
|
||||
eError = TO_IMG_ERR(err);
|
||||
goto err_exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
PVR_TRACE(("PVR DVFS activated: %lu-%lu Hz, Period: %ums",
|
||||
min_freq,
|
||||
max_freq,
|
||||
psDVFSDeviceCfg->ui32PollMs));
|
||||
|
||||
return PVRSRV_OK;
|
||||
|
||||
err_exit:
|
||||
UnregisterDVFSDevice(psDeviceNode);
|
||||
return eError;
|
||||
}
|
||||
|
||||
void UnregisterDVFSDevice(PPVRSRV_DEVICE_NODE psDeviceNode)
|
||||
{
|
||||
IMG_DVFS_DEVICE *psDVFSDevice = NULL;
|
||||
struct device *psDev = NULL;
|
||||
IMG_INT32 i32Error;
|
||||
|
||||
/* Check the device exists */
|
||||
if (!psDeviceNode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PVRSRV_VZ_RETN_IF_MODE(GUEST);
|
||||
|
||||
psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
|
||||
psDev = psDeviceNode->psDevConfig->pvOSDevice;
|
||||
|
||||
if (! psDVFSDevice)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEVFREQ_THERMAL)
|
||||
if (!IS_ERR_OR_NULL(psDVFSDevice->psDevfreqCoolingDevice))
|
||||
{
|
||||
devfreq_cooling_unregister(psDVFSDevice->psDevfreqCoolingDevice);
|
||||
psDVFSDevice->psDevfreqCoolingDevice = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (psDVFSDevice->psDevFreq)
|
||||
{
|
||||
i32Error = devfreq_unregister_opp_notifier(psDev, psDVFSDevice->psDevFreq);
|
||||
if (i32Error < 0)
|
||||
{
|
||||
PVR_DPF((PVR_DBG_ERROR, "Failed to unregister OPP notifier"));
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0))
|
||||
devfreq_remove_device(psDVFSDevice->psDevFreq);
|
||||
#else
|
||||
devm_devfreq_remove_device(psDev, psDVFSDevice->psDevFreq);
|
||||
#endif
|
||||
|
||||
psDVFSDevice->psDevFreq = NULL;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) && \
|
||||
LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
|
||||
kfree(img_devfreq_dev_profile.freq_table);
|
||||
#endif
|
||||
|
||||
psDVFSDevice->bInitPending = IMG_FALSE;
|
||||
psDVFSDevice->bReady = IMG_FALSE;
|
||||
}
|
||||
|
||||
void DeinitDVFS(PPVRSRV_DEVICE_NODE psDeviceNode)
|
||||
{
|
||||
IMG_DVFS_DEVICE *psDVFSDevice = NULL;
|
||||
struct device *psDev = NULL;
|
||||
|
||||
/* Check the device exists */
|
||||
if (!psDeviceNode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PVRSRV_VZ_RETN_IF_MODE(GUEST);
|
||||
|
||||
psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
|
||||
psDev = psDeviceNode->psDevConfig->pvOSDevice;
|
||||
|
||||
/* Remove OPP entries for this device */
|
||||
ClearOPPTable(psDev, psDeviceNode);
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) || \
|
||||
(defined(CHROMIUMOS_KERNEL) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)))
|
||||
dev_pm_opp_of_remove_table(psDev);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
SORgxGpuUtilStatsUnregister(psDVFSDevice->hGpuUtilUserDVFS);
|
||||
psDVFSDevice->hGpuUtilUserDVFS = NULL;
|
||||
psDVFSDevice->bInitPending = IMG_FALSE;
|
||||
psDVFSDevice->bReady = IMG_FALSE;
|
||||
}
|
||||
|
||||
PVRSRV_ERROR SuspendDVFS(PPVRSRV_DEVICE_NODE psDeviceNode)
|
||||
{
|
||||
IMG_DVFS_DEVICE *psDVFSDevice = NULL;
|
||||
|
||||
/* Check the device is registered */
|
||||
if (!psDeviceNode)
|
||||
{
|
||||
return PVRSRV_ERROR_INVALID_DEVICE;
|
||||
}
|
||||
|
||||
psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
|
||||
psDVFSDevice->bEnabled = IMG_FALSE;
|
||||
|
||||
return PVRSRV_OK;
|
||||
}
|
||||
|
||||
PVRSRV_ERROR ResumeDVFS(PPVRSRV_DEVICE_NODE psDeviceNode)
|
||||
{
|
||||
IMG_DVFS_DEVICE *psDVFSDevice = NULL;
|
||||
|
||||
/* Check the device is registered */
|
||||
if (!psDeviceNode)
|
||||
{
|
||||
return PVRSRV_ERROR_INVALID_DEVICE;
|
||||
}
|
||||
|
||||
psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
|
||||
|
||||
/* Not supported in GuestOS drivers */
|
||||
psDVFSDevice->bEnabled = !PVRSRV_VZ_MODE_IS(GUEST);
|
||||
|
||||
return PVRSRV_OK;
|
||||
}
|
||||
|
||||
#endif /* !NO_HARDWARE */
|
||||
62
drivers/gpu/drm/img-rogue/pvr_dvfs_device.h
Normal file
62
drivers/gpu/drm/img-rogue/pvr_dvfs_device.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*************************************************************************/ /*!
|
||||
@File pvr_dvfs.c
|
||||
@Title System level interface for DVFS
|
||||
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
|
||||
@License Dual MIT/GPLv2
|
||||
|
||||
The contents of this file are subject to the MIT license as set out below.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
the GNU General Public License Version 2 ("GPL") in which case the provisions
|
||||
of GPL are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
GPL, and not to allow others to use your version of this file under the terms
|
||||
of the MIT license, indicate your decision by deleting the provisions above
|
||||
and replace them with the notice and other provisions required by GPL as set
|
||||
out in the file called "GPL-COPYING" included in this distribution. If you do
|
||||
not delete the provisions above, a recipient may use your version of this file
|
||||
under the terms of either the MIT license or GPL.
|
||||
|
||||
This License is also included in this distribution in the file called
|
||||
"MIT-COPYING".
|
||||
|
||||
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
|
||||
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/ /**************************************************************************/
|
||||
|
||||
#ifndef PVR_DVFS_DEVICE_H
|
||||
#define PVR_DVFS_DEVICE_H
|
||||
|
||||
#include "opaque_types.h"
|
||||
#include "pvrsrv_error.h"
|
||||
|
||||
|
||||
PVRSRV_ERROR InitDVFS(PPVRSRV_DEVICE_NODE psDeviceNode);
|
||||
|
||||
void DeinitDVFS(PPVRSRV_DEVICE_NODE psDeviceNode);
|
||||
|
||||
PVRSRV_ERROR RegisterDVFSDevice(PPVRSRV_DEVICE_NODE psDeviceNode);
|
||||
|
||||
void UnregisterDVFSDevice(PPVRSRV_DEVICE_NODE psDeviceNode);
|
||||
|
||||
PVRSRV_ERROR SuspendDVFS(PPVRSRV_DEVICE_NODE psDeviceNode);
|
||||
|
||||
PVRSRV_ERROR ResumeDVFS(PPVRSRV_DEVICE_NODE psDeviceNode);
|
||||
|
||||
#endif /* PVR_DVFS_DEVICE_H */
|
||||
@@ -136,7 +136,8 @@ pvrsrvkm-y += \
|
||||
dma_support.o \
|
||||
vmm_type_stub.o \
|
||||
sysconfig.o \
|
||||
thead_sys.o
|
||||
thead_sys.o \
|
||||
pvr_dvfs_device.o
|
||||
pvrsrvkm-$(CONFIG_DRM_POWERVR_ROGUE_DEBUG) += \
|
||||
client_ri_direct_bridge.o \
|
||||
server_ri_bridge.o \
|
||||
|
||||
95
drivers/gpu/drm/img-rogue/sofunc_rgx.h
Normal file
95
drivers/gpu/drm/img-rogue/sofunc_rgx.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*************************************************************************/ /*!
|
||||
@File
|
||||
@Title SO Interface header file for devices/RGX functions
|
||||
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
|
||||
@Description Contains SO interface functions. These functions are defined in
|
||||
the common devices layer and are called from the env layer OS
|
||||
specific implementation.
|
||||
@License Dual MIT/GPLv2
|
||||
|
||||
The contents of this file are subject to the MIT license as set out below.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
the GNU General Public License Version 2 ("GPL") in which case the provisions
|
||||
of GPL are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
GPL, and not to allow others to use your version of this file under the terms
|
||||
of the MIT license, indicate your decision by deleting the provisions above
|
||||
and replace them with the notice and other provisions required by GPL as set
|
||||
out in the file called "GPL-COPYING" included in this distribution. If you do
|
||||
not delete the provisions above, a recipient may use your version of this file
|
||||
under the terms of either the MIT license or GPL.
|
||||
|
||||
This License is also included in this distribution in the file called
|
||||
"MIT-COPYING".
|
||||
|
||||
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
|
||||
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/ /**************************************************************************/
|
||||
|
||||
#if !defined(SOFUNC_RGX_H_)
|
||||
#define SOFUNC_RGX_H_
|
||||
|
||||
#include "img_types.h"
|
||||
#include "pvrsrv_error.h"
|
||||
|
||||
|
||||
#if !defined(NO_HARDWARE)
|
||||
/*!
|
||||
*******************************************************************************
|
||||
|
||||
@Function SORgxGpuUtilStatsRegister
|
||||
|
||||
@Description SO Interface function called from the OS layer implementation.
|
||||
Initialise data used to compute GPU utilisation statistics
|
||||
for a particular user (identified by the handle passed as
|
||||
argument). This function must be called only once for each
|
||||
different user/handle.
|
||||
|
||||
@Input phGpuUtilUser - Pointer to handle used to identify a user of
|
||||
RGXGetGpuUtilStats
|
||||
|
||||
@Return PVRSRV_ERROR
|
||||
|
||||
******************************************************************************/
|
||||
PVRSRV_ERROR SORgxGpuUtilStatsRegister(IMG_HANDLE *phGpuUtilUser);
|
||||
|
||||
|
||||
/*!
|
||||
*******************************************************************************
|
||||
|
||||
@Function SORgxGpuUtilStatsUnregister
|
||||
|
||||
@Description SO Interface function called from the OS layer implementation.
|
||||
Free data previously used to compute GPU utilisation statistics
|
||||
for a particular user (identified by the handle passed as
|
||||
argument).
|
||||
|
||||
@Input hGpuUtilUser - Handle used to identify a user of
|
||||
RGXGetGpuUtilStats
|
||||
|
||||
@Return PVRSRV_ERROR
|
||||
|
||||
******************************************************************************/
|
||||
PVRSRV_ERROR SORgxGpuUtilStatsUnregister(IMG_HANDLE hGpuUtilUser);
|
||||
#endif /* !defined(NO_HARDWARE) */
|
||||
|
||||
|
||||
|
||||
#endif /* SOFUNC_RGX_H_ */
|
||||
@@ -193,27 +193,6 @@ static int vs_plane_atomic_get_property(struct drm_plane *plane,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool vs_plane_format_mod_supported(struct drm_plane *plane,
|
||||
uint32_t format,
|
||||
uint64_t modifier)
|
||||
{
|
||||
struct vs_plane *vs_plane = to_vs_plane(plane);
|
||||
int i;
|
||||
|
||||
for(i = 0; i < vs_plane->info->num_modifiers; i++) {
|
||||
if (vs_plane->info->modifiers[i] == modifier)
|
||||
break;
|
||||
}
|
||||
if (i && i == vs_plane->info->num_modifiers)
|
||||
return false;
|
||||
|
||||
for(i = 0; i < vs_plane->info->num_formats; i++) {
|
||||
if (vs_plane->info->formats[i] == format)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const struct drm_plane_funcs vs_plane_funcs = {
|
||||
.update_plane = drm_atomic_helper_update_plane,
|
||||
.disable_plane = drm_atomic_helper_disable_plane,
|
||||
@@ -223,7 +202,6 @@ const struct drm_plane_funcs vs_plane_funcs = {
|
||||
.atomic_destroy_state = vs_plane_atomic_destroy_state,
|
||||
.atomic_set_property = vs_plane_atomic_set_property,
|
||||
.atomic_get_property = vs_plane_atomic_get_property,
|
||||
.format_mod_supported = vs_plane_format_mod_supported,
|
||||
};
|
||||
|
||||
static unsigned char vs_get_plane_number(struct drm_framebuffer *fb)
|
||||
@@ -322,8 +300,6 @@ struct vs_plane *vs_plane_create(struct drm_device *drm_dev,
|
||||
if (!plane)
|
||||
return NULL;
|
||||
|
||||
plane->info = info;
|
||||
|
||||
ret = drm_universal_plane_init(drm_dev, &plane->base, possible_crtcs,
|
||||
&vs_plane_funcs, info->formats,
|
||||
info->num_formats, info->modifiers, info->type,
|
||||
|
||||
@@ -47,7 +47,6 @@ struct vs_plane {
|
||||
struct drm_plane base;
|
||||
u8 id;
|
||||
dma_addr_t dma_addr[MAX_NUM_PLANES];
|
||||
struct vs_plane_info *info;
|
||||
|
||||
struct drm_property *degamma_mode;
|
||||
struct drm_property *watermark_prop;
|
||||
|
||||
@@ -868,9 +868,6 @@ static int __maybe_unused thead_dwmac_resume(struct device *dev)
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
pm_debug(dev,"enter %s()\n",__func__);
|
||||
|
||||
if (!netif_running(ndev))
|
||||
return 0;
|
||||
|
||||
if (priv->plat->init)
|
||||
priv->plat->init(pdev, priv->plat->bsp_priv);
|
||||
|
||||
|
||||
@@ -22,12 +22,6 @@ config LIGHT_REBOOTMODE
|
||||
help
|
||||
This driver supports check rebootmode feature in Light FM platform
|
||||
|
||||
config LIGHT_DDR_PMU
|
||||
tristate "Thead light ddr-pmu support"
|
||||
default m
|
||||
help
|
||||
This driver supports thead-ddr-pmu is a IP module used to do performance monitor
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
||||
|
||||
@@ -2,4 +2,3 @@
|
||||
obj-$(CONFIG_LIGHT_IOPMP) += light-iopmp.o
|
||||
obj-$(CONFIG_LIGHT_SUSPEND) += pm-light.o
|
||||
obj-$(CONFIG_LIGHT_REBOOTMODE) += light_event.o
|
||||
obj-$(CONFIG_LIGHT_DDR_PMU) += thead-ddr-pmu.o
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -317,9 +317,6 @@ endif
|
||||
DTC ?= $(objtree)/scripts/dtc/dtc
|
||||
DTC_FLAGS += $(call dtc-option,-Wno-interrupt_provider)
|
||||
|
||||
# Overlay support
|
||||
DTC_FLAGS += -@ -Wno-unit_address_format -Wno-simple_bus_reg
|
||||
|
||||
# Disable noisy checks by default
|
||||
ifeq ($(findstring 1,$(KBUILD_EXTRA_WARN)),)
|
||||
DTC_FLAGS += $(call dtc-option,-Wno-unit_address_vs_reg) \
|
||||
|
||||
@@ -112,7 +112,7 @@ dbg_dir=debian/linux-image-dbg
|
||||
perf_dir="$objtree/debian/toolstmp"
|
||||
packagename=linux-image-$version
|
||||
dbg_packagename=$packagename-dbg
|
||||
perf_packagename=linux-perf-vendor-th1520
|
||||
perf_packagename=linux-perf-thead
|
||||
|
||||
if [ "$ARCH" = "um" ] ; then
|
||||
packagename=user-mode-linux-$version
|
||||
@@ -257,7 +257,7 @@ Description: Performance analysis tools for Linux $version
|
||||
kernel version $version .
|
||||
EOF
|
||||
|
||||
mv $tools_dest/usr/bin/perf $tools_dest/usr/bin/perf-vendor-th1520
|
||||
mv $tools_dest/usr/bin/perf $tools_dest/usr/bin/perf-thead
|
||||
dpkg-shlibdeps $tools_dest/usr/bin/*
|
||||
create_package "$perf_packagename" "$perf_dir"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user