Merge branch 'linus' into perf/urgent, to resolve conflict
Conflicts: arch/powerpc/configs/85xx/kmp204x_defconfig Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
9d020d33fc
195 changed files with 13104 additions and 6931 deletions
|
@ -6,8 +6,8 @@ Required properties:
|
|||
- "fsl,imx1-pwm" for PWM compatible with the one integrated on i.MX1
|
||||
- "fsl,imx27-pwm" for PWM compatible with the one integrated on i.MX27
|
||||
- reg: physical base address and length of the controller's registers
|
||||
- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
|
||||
the cells format.
|
||||
- #pwm-cells: 2 for i.MX1 and 3 for i.MX27 and newer SoCs. See pwm.txt
|
||||
in this directory for a description of the cells format.
|
||||
- clocks : Clock specifiers for both ipg and per clocks.
|
||||
- clock-names : Clock names should include both "ipg" and "per"
|
||||
See the clock consumer binding,
|
||||
|
@ -17,7 +17,7 @@ See the clock consumer binding,
|
|||
Example:
|
||||
|
||||
pwm1: pwm@53fb4000 {
|
||||
#pwm-cells = <2>;
|
||||
#pwm-cells = <3>;
|
||||
compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
|
||||
reg = <0x53fb4000 0x4000>;
|
||||
clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
|
||||
|
|
|
@ -17,6 +17,12 @@ Required properties:
|
|||
calibration data, as specified by the SoC reference manual.
|
||||
The first cell of each pair is the value to be written to TTCFGR,
|
||||
and the second is the value to be written to TSCFGR.
|
||||
- #thermal-sensor-cells : Must be 1. The sensor specifier is the monitoring
|
||||
site ID, and represents the "n" in TRITSRn and TRATSRn.
|
||||
|
||||
Optional property:
|
||||
- little-endian : If present, the TMU registers are little endian. If absent,
|
||||
the default is big endian.
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -60,4 +66,5 @@ tmu@f0000 {
|
|||
|
||||
0x00030000 0x00000012
|
||||
0x00030001 0x0000001d>;
|
||||
#thermal-sensor-cells = <1>;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
* DT bindings for Renesas R-Car Gen3 Thermal Sensor driver
|
||||
|
||||
On R-Car Gen3 SoCs, the thermal sensor controllers (TSC) control the thermal
|
||||
sensors (THS) which are the analog circuits for measuring temperature (Tj)
|
||||
inside the LSI.
|
||||
|
||||
Required properties:
|
||||
- compatible : "renesas,<soctype>-thermal",
|
||||
Examples with soctypes are:
|
||||
- "renesas,r8a7795-thermal" (R-Car H3)
|
||||
- "renesas,r8a7796-thermal" (R-Car M3-W)
|
||||
- reg : Address ranges of the thermal registers. Each sensor
|
||||
needs one address range. Sorting must be done in
|
||||
increasing order according to datasheet, i.e.
|
||||
TSC1, TSC2, ...
|
||||
- clocks : Must contain a reference to the functional clock.
|
||||
- #thermal-sensor-cells : must be <1>.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- interrupts : interrupts routed to the TSC (3 for H3 and M3-W)
|
||||
- power-domain : Must contain a reference to the power domain. This
|
||||
property is mandatory if the thermal sensor instance
|
||||
is part of a controllable power domain.
|
||||
|
||||
Example:
|
||||
|
||||
tsc: thermal@e6198000 {
|
||||
compatible = "renesas,r8a7795-thermal";
|
||||
reg = <0 0xe6198000 0 0x68>,
|
||||
<0 0xe61a0000 0 0x5c>,
|
||||
<0 0xe61a8000 0 0x5c>;
|
||||
interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cpg CPG_MOD 522>;
|
||||
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
|
||||
#thermal-sensor-cells = <1>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
sensor_thermal1: sensor-thermal1 {
|
||||
polling-delay-passive = <250>;
|
||||
polling-delay = <1000>;
|
||||
thermal-sensors = <&tsc 0>;
|
||||
|
||||
trips {
|
||||
sensor1_crit: sensor1-crit {
|
||||
temperature = <90000>;
|
||||
hysteresis = <2000>;
|
||||
type = "critical";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
116
Documentation/devicetree/bindings/thermal/zx2967-thermal.txt
Normal file
116
Documentation/devicetree/bindings/thermal/zx2967-thermal.txt
Normal file
|
@ -0,0 +1,116 @@
|
|||
* ZTE zx2967 family Thermal
|
||||
|
||||
Required Properties:
|
||||
- compatible: should be one of the following.
|
||||
* zte,zx296718-thermal
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- clocks : Pairs of phandle and specifier referencing the controller's clocks.
|
||||
- clock-names: "topcrm" for the topcrm clock.
|
||||
"apb" for the apb clock.
|
||||
- #thermal-sensor-cells: must be 0.
|
||||
|
||||
Please note: slope coefficient defined in thermal-zones section need to be
|
||||
multiplied by 1000.
|
||||
|
||||
Example for tempsensor:
|
||||
|
||||
tempsensor: tempsensor@148a000 {
|
||||
compatible = "zte,zx296718-thermal";
|
||||
reg = <0x0148a000 0x20>;
|
||||
clocks = <&topcrm TEMPSENSOR_GATE>, <&audiocrm AUDIO_TS_PCLK>;
|
||||
clock-names = "topcrm", "apb";
|
||||
#thermal-sensor-cells = <0>;
|
||||
};
|
||||
|
||||
Example for cooling device:
|
||||
|
||||
cooling_dev: cooling_dev {
|
||||
cluster0_cooling_dev: cluster0-cooling-dev {
|
||||
#cooling-cells = <2>;
|
||||
cpumask = <0xf>;
|
||||
capacitance = <1500>;
|
||||
};
|
||||
|
||||
cluster1_cooling_dev: cluster1-cooling-dev {
|
||||
#cooling-cells = <2>;
|
||||
cpumask = <0x30>;
|
||||
capacitance = <2000>;
|
||||
};
|
||||
};
|
||||
|
||||
Example for thermal zones:
|
||||
|
||||
thermal-zones {
|
||||
zx296718_thermal: zx296718_thermal {
|
||||
polling-delay-passive = <500>;
|
||||
polling-delay = <1000>;
|
||||
sustainable-power = <6500>;
|
||||
|
||||
thermal-sensors = <&tempsensor 0>;
|
||||
/*
|
||||
* slope need to be multiplied by 1000.
|
||||
*/
|
||||
coefficients = <1951 (-922)>;
|
||||
|
||||
trips {
|
||||
trip0: switch_on_temperature {
|
||||
temperature = <90000>;
|
||||
hysteresis = <2000>;
|
||||
type = "passive";
|
||||
};
|
||||
|
||||
trip1: desired_temperature {
|
||||
temperature = <100000>;
|
||||
hysteresis = <2000>;
|
||||
type = "passive";
|
||||
};
|
||||
|
||||
crit: critical_temperature {
|
||||
temperature = <110000>;
|
||||
hysteresis = <2000>;
|
||||
type = "critical";
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
map0 {
|
||||
trip = <&trip0>;
|
||||
cooling-device = <&gpu 2 5>;
|
||||
};
|
||||
|
||||
map1 {
|
||||
trip = <&trip0>;
|
||||
cooling-device = <&cluster0_cooling_dev 1 2>;
|
||||
};
|
||||
|
||||
map2 {
|
||||
trip = <&trip1>;
|
||||
cooling-device = <&cluster0_cooling_dev 1 2>;
|
||||
};
|
||||
|
||||
map3 {
|
||||
trip = <&crit>;
|
||||
cooling-device = <&cluster0_cooling_dev 1 2>;
|
||||
};
|
||||
|
||||
map4 {
|
||||
trip = <&trip0>;
|
||||
cooling-device = <&cluster1_cooling_dev 1 2>;
|
||||
contribution = <9000>;
|
||||
};
|
||||
|
||||
map5 {
|
||||
trip = <&trip1>;
|
||||
cooling-device = <&cluster1_cooling_dev 1 2>;
|
||||
contribution = <4096>;
|
||||
};
|
||||
|
||||
map6 {
|
||||
trip = <&crit>;
|
||||
cooling-device = <&cluster1_cooling_dev 1 2>;
|
||||
contribution = <4096>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -125,13 +125,14 @@ active_logs=%u Support configuring the number of active logs. In the
|
|||
disable_ext_identify Disable the extension list configured by mkfs, so f2fs
|
||||
does not aware of cold files such as media files.
|
||||
inline_xattr Enable the inline xattrs feature.
|
||||
noinline_xattr Disable the inline xattrs feature.
|
||||
inline_data Enable the inline data feature: New created small(<~3.4k)
|
||||
files can be written into inode block.
|
||||
inline_dentry Enable the inline dir feature: data in new created
|
||||
directory entries can be written into inode block. The
|
||||
space of inode block which is used to store inline
|
||||
dentries is limited to ~3.4k.
|
||||
noinline_dentry Diable the inline dentry feature.
|
||||
noinline_dentry Disable the inline dentry feature.
|
||||
flush_merge Merge concurrent cache_flush commands as much as possible
|
||||
to eliminate redundant command issues. If the underlying
|
||||
device handles the cache_flush command relatively slowly,
|
||||
|
@ -157,6 +158,8 @@ data_flush Enable data flushing before checkpoint in order to
|
|||
mode=%s Control block allocation mode which supports "adaptive"
|
||||
and "lfs". In "lfs" mode, there should be no random
|
||||
writes towards main area.
|
||||
io_bits=%u Set the bit size of write IO requests. It should be set
|
||||
with "mode=lfs".
|
||||
|
||||
================================================================================
|
||||
DEBUGFS ENTRIES
|
||||
|
@ -174,7 +177,7 @@ f2fs. Each file shows the whole f2fs information.
|
|||
SYSFS ENTRIES
|
||||
================================================================================
|
||||
|
||||
Information about mounted f2f2 file systems can be found in
|
||||
Information about mounted f2fs file systems can be found in
|
||||
/sys/fs/f2fs. Each mounted filesystem will have a directory in
|
||||
/sys/fs/f2fs based on its device name (i.e., /sys/fs/f2fs/sda).
|
||||
The files in each per-device directory are shown in table below.
|
||||
|
|
|
@ -7483,18 +7483,24 @@ L: linuxppc-dev@lists.ozlabs.org
|
|||
Q: http://patchwork.ozlabs.org/project/linuxppc-dev/list/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git
|
||||
S: Supported
|
||||
F: Documentation/ABI/stable/sysfs-firmware-opal-*
|
||||
F: Documentation/devicetree/bindings/powerpc/opal/
|
||||
F: Documentation/devicetree/bindings/rtc/rtc-opal.txt
|
||||
F: Documentation/devicetree/bindings/i2c/i2c-opal.txt
|
||||
F: Documentation/powerpc/
|
||||
F: arch/powerpc/
|
||||
F: drivers/char/tpm/tpm_ibmvtpm*
|
||||
F: drivers/crypto/nx/
|
||||
F: drivers/crypto/vmx/
|
||||
F: drivers/i2c/busses/i2c-opal.c
|
||||
F: drivers/net/ethernet/ibm/ibmveth.*
|
||||
F: drivers/net/ethernet/ibm/ibmvnic.*
|
||||
F: drivers/pci/hotplug/pnv_php.c
|
||||
F: drivers/pci/hotplug/rpa*
|
||||
F: drivers/rtc/rtc-opal.c
|
||||
F: drivers/scsi/ibmvscsi/
|
||||
F: drivers/tty/hvc/hvc_opal.c
|
||||
F: tools/testing/selftests/powerpc
|
||||
N: opal
|
||||
N: /pmac
|
||||
N: powermac
|
||||
N: powernv
|
||||
|
|
|
@ -184,16 +184,22 @@ static inline u64 arm64_ftr_reg_user_value(const struct arm64_ftr_reg *reg)
|
|||
}
|
||||
|
||||
static inline int __attribute_const__
|
||||
cpuid_feature_extract_field(u64 features, int field, bool sign)
|
||||
cpuid_feature_extract_field_width(u64 features, int field, int width, bool sign)
|
||||
{
|
||||
return (sign) ?
|
||||
cpuid_feature_extract_signed_field(features, field) :
|
||||
cpuid_feature_extract_unsigned_field(features, field);
|
||||
cpuid_feature_extract_signed_field_width(features, field, width) :
|
||||
cpuid_feature_extract_unsigned_field_width(features, field, width);
|
||||
}
|
||||
|
||||
static inline int __attribute_const__
|
||||
cpuid_feature_extract_field(u64 features, int field, bool sign)
|
||||
{
|
||||
return cpuid_feature_extract_field_width(features, field, 4, sign);
|
||||
}
|
||||
|
||||
static inline s64 arm64_ftr_value(const struct arm64_ftr_bits *ftrp, u64 val)
|
||||
{
|
||||
return (s64)cpuid_feature_extract_field(val, ftrp->shift, ftrp->sign);
|
||||
return (s64)cpuid_feature_extract_field_width(val, ftrp->shift, ftrp->width, ftrp->sign);
|
||||
}
|
||||
|
||||
static inline bool id_aa64mmfr0_mixed_endian_el0(u64 mmfr0)
|
||||
|
|
|
@ -109,10 +109,8 @@ static bool pgattr_change_is_safe(u64 old, u64 new)
|
|||
static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
|
||||
unsigned long end, unsigned long pfn,
|
||||
pgprot_t prot,
|
||||
phys_addr_t (*pgtable_alloc)(void),
|
||||
bool page_mappings_only)
|
||||
phys_addr_t (*pgtable_alloc)(void))
|
||||
{
|
||||
pgprot_t __prot = prot;
|
||||
pte_t *pte;
|
||||
|
||||
BUG_ON(pmd_sect(*pmd));
|
||||
|
@ -130,18 +128,7 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
|
|||
do {
|
||||
pte_t old_pte = *pte;
|
||||
|
||||
/*
|
||||
* Set the contiguous bit for the subsequent group of PTEs if
|
||||
* its size and alignment are appropriate.
|
||||
*/
|
||||
if (((addr | PFN_PHYS(pfn)) & ~CONT_PTE_MASK) == 0) {
|
||||
if (end - addr >= CONT_PTE_SIZE && !page_mappings_only)
|
||||
__prot = __pgprot(pgprot_val(prot) | PTE_CONT);
|
||||
else
|
||||
__prot = prot;
|
||||
}
|
||||
|
||||
set_pte(pte, pfn_pte(pfn, __prot));
|
||||
set_pte(pte, pfn_pte(pfn, prot));
|
||||
pfn++;
|
||||
|
||||
/*
|
||||
|
@ -160,7 +147,6 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
|
|||
phys_addr_t (*pgtable_alloc)(void),
|
||||
bool page_mappings_only)
|
||||
{
|
||||
pgprot_t __prot = prot;
|
||||
pmd_t *pmd;
|
||||
unsigned long next;
|
||||
|
||||
|
@ -187,18 +173,7 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
|
|||
/* try section mapping first */
|
||||
if (((addr | next | phys) & ~SECTION_MASK) == 0 &&
|
||||
!page_mappings_only) {
|
||||
/*
|
||||
* Set the contiguous bit for the subsequent group of
|
||||
* PMDs if its size and alignment are appropriate.
|
||||
*/
|
||||
if (((addr | phys) & ~CONT_PMD_MASK) == 0) {
|
||||
if (end - addr >= CONT_PMD_SIZE)
|
||||
__prot = __pgprot(pgprot_val(prot) |
|
||||
PTE_CONT);
|
||||
else
|
||||
__prot = prot;
|
||||
}
|
||||
pmd_set_huge(pmd, phys, __prot);
|
||||
pmd_set_huge(pmd, phys, prot);
|
||||
|
||||
/*
|
||||
* After the PMD entry has been populated once, we
|
||||
|
@ -208,8 +183,7 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
|
|||
pmd_val(*pmd)));
|
||||
} else {
|
||||
alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys),
|
||||
prot, pgtable_alloc,
|
||||
page_mappings_only);
|
||||
prot, pgtable_alloc);
|
||||
|
||||
BUG_ON(pmd_val(old_pmd) != 0 &&
|
||||
pmd_val(old_pmd) != pmd_val(*pmd));
|
||||
|
|
|
@ -138,7 +138,7 @@ ENDPROC(cpu_do_resume)
|
|||
* - pgd_phys - physical address of new TTB
|
||||
*/
|
||||
ENTRY(cpu_do_switch_mm)
|
||||
pre_ttbr0_update_workaround x0, x1, x2
|
||||
pre_ttbr0_update_workaround x0, x2, x3
|
||||
mmid x1, x1 // get mm->context.id
|
||||
bfi x0, x1, #48, #16 // set the ASID
|
||||
msr ttbr0_el1, x0 // set TTBR0
|
||||
|
|
|
@ -115,7 +115,7 @@ config PPC
|
|||
select HAVE_PERF_REGS
|
||||
select HAVE_PERF_USER_STACK_DUMP
|
||||
select HAVE_REGS_AND_STACK_ACCESS_API
|
||||
select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64
|
||||
select HAVE_HW_BREAKPOINT if PERF_EVENTS && (PPC_BOOK3S || PPC_8xx)
|
||||
select ARCH_WANT_IPC_PARSE_VERSION
|
||||
select SPARSE_IRQ
|
||||
select IRQ_DOMAIN
|
||||
|
|
303
arch/powerpc/boot/dts/fsl/kmcent2.dts
Normal file
303
arch/powerpc/boot/dts/fsl/kmcent2.dts
Normal file
|
@ -0,0 +1,303 @@
|
|||
/*
|
||||
* Keymile kmcent2 Device Tree Source, based on T1040RDB DTS
|
||||
*
|
||||
* (C) Copyright 2016
|
||||
* Valentin Longchamp, Keymile AG, valentin.longchamp@keymile.com
|
||||
*
|
||||
* Copyright 2014 - 2015 Freescale Semiconductor Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/include/ "t104xsi-pre.dtsi"
|
||||
|
||||
/ {
|
||||
model = "keymile,kmcent2";
|
||||
compatible = "keymile,kmcent2";
|
||||
|
||||
aliases {
|
||||
front_phy = &front_phy;
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
bman_fbpr: bman-fbpr {
|
||||
size = <0 0x1000000>;
|
||||
alignment = <0 0x1000000>;
|
||||
};
|
||||
qman_fqd: qman-fqd {
|
||||
size = <0 0x400000>;
|
||||
alignment = <0 0x400000>;
|
||||
};
|
||||
qman_pfdr: qman-pfdr {
|
||||
size = <0 0x2000000>;
|
||||
alignment = <0 0x2000000>;
|
||||
};
|
||||
};
|
||||
|
||||
ifc: localbus@ffe124000 {
|
||||
reg = <0xf 0xfe124000 0 0x2000>;
|
||||
ranges = <0 0 0xf 0xe8000000 0x04000000
|
||||
1 0 0xf 0xfa000000 0x00010000
|
||||
2 0 0xf 0xfb000000 0x00010000
|
||||
4 0 0xf 0xc0000000 0x08000000
|
||||
6 0 0xf 0xd0000000 0x08000000
|
||||
7 0 0xf 0xd8000000 0x08000000>;
|
||||
|
||||
nor@0,0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "cfi-flash";
|
||||
reg = <0x0 0x0 0x04000000>;
|
||||
bank-width = <2>;
|
||||
device-width = <2>;
|
||||
};
|
||||
|
||||
nand@1,0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,ifc-nand";
|
||||
reg = <0x1 0x0 0x10000>;
|
||||
};
|
||||
|
||||
board-control@2,0 {
|
||||
compatible = "keymile,qriox";
|
||||
reg = <0x2 0x0 0x80>;
|
||||
};
|
||||
|
||||
chassis-mgmt@6,0 {
|
||||
compatible = "keymile,bfticu";
|
||||
reg = <6 0 0x100>;
|
||||
interrupt-controller;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <11 1 0 0>;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
};
|
||||
|
||||
dcsr: dcsr@f00000000 {
|
||||
ranges = <0x00000000 0xf 0x00000000 0x01072000>;
|
||||
};
|
||||
|
||||
bportals: bman-portals@ff4000000 {
|
||||
ranges = <0x0 0xf 0xf4000000 0x2000000>;
|
||||
};
|
||||
|
||||
qportals: qman-portals@ff6000000 {
|
||||
ranges = <0x0 0xf 0xf6000000 0x2000000>;
|
||||
};
|
||||
|
||||
soc: soc@ffe000000 {
|
||||
ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
|
||||
reg = <0xf 0xfe000000 0 0x00001000>;
|
||||
|
||||
spi@110000 {
|
||||
network-clock@1 {
|
||||
compatible = "zarlink,zl30364";
|
||||
reg = <1>;
|
||||
spi-max-frequency = <1000000>;
|
||||
};
|
||||
};
|
||||
|
||||
sdhc@114000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c@118000 {
|
||||
clock-frequency = <100000>;
|
||||
|
||||
mux@70 {
|
||||
compatible = "nxp,pca9547";
|
||||
reg = <0x70>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
i2c-mux-idle-disconnect;
|
||||
|
||||
i2c@0 {
|
||||
reg = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
eeprom@54 {
|
||||
compatible = "24c02";
|
||||
reg = <0x54>;
|
||||
pagesize = <2>;
|
||||
read-only;
|
||||
label = "ddr3-spd";
|
||||
};
|
||||
};
|
||||
|
||||
i2c@7 {
|
||||
reg = <7>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
temp-sensor@48 {
|
||||
compatible = "national,lm75";
|
||||
reg = <0x48>;
|
||||
label = "SENSOR_0";
|
||||
};
|
||||
temp-sensor@4a {
|
||||
compatible = "national,lm75";
|
||||
reg = <0x4a>;
|
||||
label = "SENSOR_2";
|
||||
};
|
||||
temp-sensor@4b {
|
||||
compatible = "national,lm75";
|
||||
reg = <0x4b>;
|
||||
label = "SENSOR_3";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
i2c@118100 {
|
||||
clock-frequency = <100000>;
|
||||
|
||||
eeprom@50 {
|
||||
compatible = "atmel,24c08";
|
||||
reg = <0x50>;
|
||||
pagesize = <16>;
|
||||
};
|
||||
|
||||
eeprom@54 {
|
||||
compatible = "atmel,24c08";
|
||||
reg = <0x54>;
|
||||
pagesize = <16>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c@119000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c@119100 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
serial2: serial@11d500 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
serial3: serial@11d600 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb0: usb@210000 {
|
||||
status = "disabled";
|
||||
};
|
||||
usb1: usb@211000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
display@180000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
sata@220000 {
|
||||
status = "disabled";
|
||||
};
|
||||
sata@221000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
fman@400000 {
|
||||
ethernet@e0000 {
|
||||
fixed-link = <0 1 1000 0 0>;
|
||||
phy-connection-type = "sgmii";
|
||||
};
|
||||
|
||||
ethernet@e2000 {
|
||||
fixed-link = <1 1 1000 0 0>;
|
||||
phy-connection-type = "sgmii";
|
||||
};
|
||||
|
||||
ethernet@e4000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ethernet@e6000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ethernet@e8000 {
|
||||
phy-handle = <&front_phy>;
|
||||
phy-connection-type = "rgmii";
|
||||
};
|
||||
|
||||
mdio0: mdio@fc000 {
|
||||
front_phy: ethernet-phy@11 {
|
||||
reg = <0x11>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
pci0: pcie@ffe240000 {
|
||||
reg = <0xf 0xfe240000 0 0x10000>;
|
||||
ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
|
||||
0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
|
||||
pcie@0 {
|
||||
ranges = <0x02000000 0 0xe0000000
|
||||
0x02000000 0 0xe0000000
|
||||
0 0x20000000
|
||||
|
||||
0x01000000 0 0x00000000
|
||||
0x01000000 0 0x00000000
|
||||
0 0x00010000>;
|
||||
};
|
||||
};
|
||||
|
||||
pci1: pcie@ffe250000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pci2: pcie@ffe260000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pci3: pcie@ffe270000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
qe: qe@ffe140000 {
|
||||
ranges = <0x0 0xf 0xfe140000 0x40000>;
|
||||
reg = <0xf 0xfe140000 0 0x480>;
|
||||
brg-frequency = <0>;
|
||||
bus-frequency = <0>;
|
||||
|
||||
si1: si@700 {
|
||||
compatible = "fsl,t1040-qe-si";
|
||||
reg = <0x700 0x80>;
|
||||
};
|
||||
|
||||
siram1: siram@1000 {
|
||||
compatible = "fsl,t1040-qe-siram";
|
||||
reg = <0x1000 0x800>;
|
||||
};
|
||||
|
||||
ucc_hdlc: ucc@2000 {
|
||||
device_type = "hdlc";
|
||||
compatible = "fsl,ucc-hdlc";
|
||||
rx-clock-name = "clk9";
|
||||
tx-clock-name = "clk9";
|
||||
fsl,tx-timeslot-mask = <0xfffffffe>;
|
||||
fsl,rx-timeslot-mask = <0xfffffffe>;
|
||||
fsl,siram-entry-id = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#include "t1040si-post.dtsi"
|
|
@ -83,6 +83,10 @@
|
|||
};
|
||||
};
|
||||
|
||||
sdhc@114000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c@119000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
|
@ -422,7 +422,7 @@
|
|||
0x00030001 0x0000000d
|
||||
0x00030002 0x00000019
|
||||
0x00030003 0x00000024>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
#thermal-sensor-cells = <1>;
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
|
@ -430,7 +430,7 @@
|
|||
polling-delay-passive = <1000>;
|
||||
polling-delay = <5000>;
|
||||
|
||||
thermal-sensors = <&tmu>;
|
||||
thermal-sensors = <&tmu 0>;
|
||||
|
||||
trips {
|
||||
cpu_alert: cpu-alert {
|
||||
|
|
|
@ -526,7 +526,7 @@
|
|||
|
||||
0x00030000 0x00000012
|
||||
0x00030001 0x0000001d>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
#thermal-sensor-cells = <1>;
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
|
@ -534,7 +534,7 @@
|
|||
polling-delay-passive = <1000>;
|
||||
polling-delay = <5000>;
|
||||
|
||||
thermal-sensors = <&tmu>;
|
||||
thermal-sensors = <&tmu 2>;
|
||||
|
||||
trips {
|
||||
cpu_alert: cpu-alert {
|
||||
|
|
|
@ -1,220 +0,0 @@
|
|||
CONFIG_PPC_85xx=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=8
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
CONFIG_AUDIT=y
|
||||
CONFIG_NO_HZ=y
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_BSD_PROCESS_ACCT=y
|
||||
CONFIG_IKCONFIG=y
|
||||
CONFIG_IKCONFIG_PROC=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
CONFIG_CGROUPS=y
|
||||
CONFIG_CGROUP_SCHED=y
|
||||
CONFIG_RELAY=y
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
CONFIG_EMBEDDED=y
|
||||
CONFIG_PERF_EVENTS=y
|
||||
CONFIG_SLAB=y
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
CONFIG_MODULE_FORCE_UNLOAD=y
|
||||
CONFIG_MODVERSIONS=y
|
||||
# CONFIG_BLK_DEV_BSG is not set
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
CONFIG_MAC_PARTITION=y
|
||||
CONFIG_CORENET_GENERIC=y
|
||||
CONFIG_MPIC_MSGR=y
|
||||
CONFIG_HIGHMEM=y
|
||||
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
|
||||
CONFIG_BINFMT_MISC=m
|
||||
CONFIG_KEXEC=y
|
||||
CONFIG_FORCE_MAX_ZONEORDER=13
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCIEPORTBUS=y
|
||||
# CONFIG_PCIEASPM is not set
|
||||
CONFIG_PCI_MSI=y
|
||||
CONFIG_ADVANCED_OPTIONS=y
|
||||
CONFIG_LOWMEM_SIZE_BOOL=y
|
||||
CONFIG_LOWMEM_SIZE=0x20000000
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_UNIX=y
|
||||
CONFIG_XFRM_USER=y
|
||||
CONFIG_XFRM_SUB_POLICY=y
|
||||
CONFIG_XFRM_STATISTICS=y
|
||||
CONFIG_NET_KEY=y
|
||||
CONFIG_NET_KEY_MIGRATE=y
|
||||
CONFIG_INET=y
|
||||
CONFIG_IP_MULTICAST=y
|
||||
CONFIG_IP_ADVANCED_ROUTER=y
|
||||
CONFIG_IP_MULTIPLE_TABLES=y
|
||||
CONFIG_IP_ROUTE_MULTIPATH=y
|
||||
CONFIG_IP_ROUTE_VERBOSE=y
|
||||
CONFIG_IP_PNP=y
|
||||
CONFIG_IP_PNP_DHCP=y
|
||||
CONFIG_IP_PNP_BOOTP=y
|
||||
CONFIG_IP_PNP_RARP=y
|
||||
CONFIG_NET_IPIP=y
|
||||
CONFIG_IP_MROUTE=y
|
||||
CONFIG_IP_PIMSM_V1=y
|
||||
CONFIG_IP_PIMSM_V2=y
|
||||
CONFIG_INET_AH=y
|
||||
CONFIG_INET_ESP=y
|
||||
CONFIG_INET_IPCOMP=y
|
||||
CONFIG_IPV6=y
|
||||
CONFIG_IP_SCTP=m
|
||||
CONFIG_TIPC=y
|
||||
CONFIG_NET_SCHED=y
|
||||
CONFIG_NET_SCH_CBQ=y
|
||||
CONFIG_NET_SCH_HTB=y
|
||||
CONFIG_NET_SCH_HFSC=y
|
||||
CONFIG_NET_SCH_PRIO=y
|
||||
CONFIG_NET_SCH_MULTIQ=y
|
||||
CONFIG_NET_SCH_RED=y
|
||||
CONFIG_NET_SCH_SFQ=y
|
||||
CONFIG_NET_SCH_TEQL=y
|
||||
CONFIG_NET_SCH_TBF=y
|
||||
CONFIG_NET_SCH_GRED=y
|
||||
CONFIG_NET_CLS_BASIC=y
|
||||
CONFIG_NET_CLS_TCINDEX=y
|
||||
CONFIG_NET_CLS_U32=y
|
||||
CONFIG_CLS_U32_PERF=y
|
||||
CONFIG_CLS_U32_MARK=y
|
||||
CONFIG_NET_CLS_FLOW=y
|
||||
CONFIG_NET_CLS_CGROUP=y
|
||||
CONFIG_UEVENT_HELPER_PATH="/sbin/mdev"
|
||||
CONFIG_DEVTMPFS=y
|
||||
CONFIG_MTD=y
|
||||
CONFIG_MTD_CMDLINE_PARTS=y
|
||||
CONFIG_MTD_BLOCK=y
|
||||
CONFIG_MTD_CFI=y
|
||||
CONFIG_MTD_CFI_AMDSTD=y
|
||||
CONFIG_MTD_PHYSMAP_OF=y
|
||||
CONFIG_MTD_PHRAM=y
|
||||
CONFIG_MTD_NAND=y
|
||||
CONFIG_MTD_NAND_ECC_BCH=y
|
||||
CONFIG_MTD_NAND_FSL_ELBC=y
|
||||
CONFIG_MTD_UBI=y
|
||||
CONFIG_MTD_UBI_GLUEBI=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_COUNT=2
|
||||
CONFIG_BLK_DEV_RAM_SIZE=2048
|
||||
CONFIG_EEPROM_AT24=y
|
||||
CONFIG_SCSI=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_CHR_DEV_ST=y
|
||||
CONFIG_BLK_DEV_SR=y
|
||||
CONFIG_CHR_DEV_SG=y
|
||||
CONFIG_SCSI_LOGGING=y
|
||||
CONFIG_SCSI_SYM53C8XX_2=y
|
||||
CONFIG_NETDEVICES=y
|
||||
# CONFIG_NET_VENDOR_3COM is not set
|
||||
# CONFIG_NET_VENDOR_ADAPTEC is not set
|
||||
# CONFIG_NET_VENDOR_ALTEON is not set
|
||||
# CONFIG_NET_VENDOR_AMD is not set
|
||||
# CONFIG_NET_VENDOR_ATHEROS is not set
|
||||
# CONFIG_NET_VENDOR_BROADCOM is not set
|
||||
# CONFIG_NET_VENDOR_BROCADE is not set
|
||||
# CONFIG_NET_VENDOR_CHELSIO is not set
|
||||
# CONFIG_NET_VENDOR_CISCO is not set
|
||||
# CONFIG_NET_VENDOR_DEC is not set
|
||||
# CONFIG_NET_VENDOR_DLINK is not set
|
||||
# CONFIG_NET_VENDOR_EMULEX is not set
|
||||
# CONFIG_NET_VENDOR_EXAR is not set
|
||||
CONFIG_FSL_PQ_MDIO=y
|
||||
CONFIG_FSL_XGMAC_MDIO=y
|
||||
# CONFIG_NET_VENDOR_HP is not set
|
||||
# CONFIG_NET_VENDOR_INTEL is not set
|
||||
# CONFIG_NET_VENDOR_MARVELL is not set
|
||||
# CONFIG_NET_VENDOR_MELLANOX is not set
|
||||
# CONFIG_NET_VENDOR_MICREL is not set
|
||||
# CONFIG_NET_VENDOR_MICROCHIP is not set
|
||||
# CONFIG_NET_VENDOR_MYRI is not set
|
||||
# CONFIG_NET_VENDOR_NATSEMI is not set
|
||||
# CONFIG_NET_VENDOR_NVIDIA is not set
|
||||
# CONFIG_NET_VENDOR_OKI is not set
|
||||
# CONFIG_NET_PACKET_ENGINE is not set
|
||||
# CONFIG_NET_VENDOR_QLOGIC is not set
|
||||
# CONFIG_NET_VENDOR_REALTEK is not set
|
||||
# CONFIG_NET_VENDOR_RDC is not set
|
||||
# CONFIG_NET_VENDOR_SEEQ is not set
|
||||
# CONFIG_NET_VENDOR_SILAN is not set
|
||||
# CONFIG_NET_VENDOR_SIS is not set
|
||||
# CONFIG_NET_VENDOR_SMSC is not set
|
||||
# CONFIG_NET_VENDOR_STMICRO is not set
|
||||
# CONFIG_NET_VENDOR_SUN is not set
|
||||
# CONFIG_NET_VENDOR_TEHUTI is not set
|
||||
# CONFIG_NET_VENDOR_TI is not set
|
||||
# CONFIG_NET_VENDOR_VIA is not set
|
||||
# CONFIG_NET_VENDOR_WIZNET is not set
|
||||
# CONFIG_NET_VENDOR_XILINX is not set
|
||||
CONFIG_MARVELL_PHY=y
|
||||
CONFIG_VITESSE_PHY=y
|
||||
CONFIG_FIXED_PHY=y
|
||||
# CONFIG_WLAN is not set
|
||||
# CONFIG_INPUT_MOUSEDEV is not set
|
||||
# CONFIG_INPUT_KEYBOARD is not set
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
CONFIG_SERIO_LIBPS2=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
CONFIG_PPC_EPAPR_HV_BYTECHAN=y
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_MANY_PORTS=y
|
||||
CONFIG_SERIAL_8250_DETECT_IRQ=y
|
||||
CONFIG_SERIAL_8250_RSA=y
|
||||
CONFIG_NVRAM=y
|
||||
CONFIG_I2C=y
|
||||
CONFIG_I2C_CHARDEV=y
|
||||
CONFIG_I2C_MUX=y
|
||||
CONFIG_I2C_MUX_PCA954x=y
|
||||
CONFIG_I2C_MPC=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SPI_FSL_SPI=y
|
||||
CONFIG_SPI_FSL_ESPI=y
|
||||
CONFIG_SPI_SPIDEV=m
|
||||
CONFIG_PTP_1588_CLOCK=y
|
||||
# CONFIG_HWMON is not set
|
||||
# CONFIG_USB_SUPPORT is not set
|
||||
CONFIG_EDAC=y
|
||||
CONFIG_EDAC_MM_EDAC=y
|
||||
CONFIG_EDAC_MPC85XX=y
|
||||
CONFIG_RTC_CLASS=y
|
||||
CONFIG_RTC_DRV_DS3232=y
|
||||
CONFIG_RTC_DRV_CMOS=y
|
||||
CONFIG_UIO=y
|
||||
CONFIG_STAGING=y
|
||||
CONFIG_CLK_QORIQ=y
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_NTFS_FS=y
|
||||
CONFIG_PROC_KCORE=y
|
||||
CONFIG_TMPFS=y
|
||||
CONFIG_JFFS2_FS=y
|
||||
CONFIG_UBIFS_FS=y
|
||||
CONFIG_CRAMFS=y
|
||||
CONFIG_SQUASHFS=y
|
||||
CONFIG_SQUASHFS_XZ=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_NLS_UTF8=m
|
||||
CONFIG_CRC_ITU_T=m
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_SHIRQ=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
CONFIG_SCHEDSTATS=y
|
||||
CONFIG_RCU_TRACE=y
|
||||
CONFIG_UPROBE_EVENTS=y
|
||||
CONFIG_CRYPTO_NULL=y
|
||||
CONFIG_CRYPTO_PCBC=m
|
||||
CONFIG_CRYPTO_MD4=y
|
||||
CONFIG_CRYPTO_SHA256=y
|
||||
CONFIG_CRYPTO_SHA512=y
|
||||
# CONFIG_CRYPTO_ANSI_CPRNG is not set
|
||||
CONFIG_CRYPTO_DEV_FSL_CAAM=y
|
|
@ -58,7 +58,6 @@ CONFIG_KEXEC_FILE=y
|
|||
CONFIG_IRQ_ALL_CPUS=y
|
||||
CONFIG_MEMORY_HOTPLUG=y
|
||||
CONFIG_MEMORY_HOTREMOVE=y
|
||||
CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=y
|
||||
CONFIG_KSM=y
|
||||
CONFIG_TRANSPARENT_HUGEPAGE=y
|
||||
CONFIG_PPC_64K_PAGES=y
|
||||
|
|
|
@ -154,6 +154,34 @@ static __inline__ int test_and_change_bit(unsigned long nr,
|
|||
return test_and_change_bits(BIT_MASK(nr), addr + BIT_WORD(nr)) != 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
static __inline__ unsigned long clear_bit_unlock_return_word(int nr,
|
||||
volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long old, t;
|
||||
unsigned long *p = (unsigned long *)addr + BIT_WORD(nr);
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
|
||||
__asm__ __volatile__ (
|
||||
PPC_RELEASE_BARRIER
|
||||
"1:" PPC_LLARX(%0,0,%3,0) "\n"
|
||||
"andc %1,%0,%2\n"
|
||||
PPC405_ERR77(0,%3)
|
||||
PPC_STLCX "%1,0,%3\n"
|
||||
"bne- 1b\n"
|
||||
: "=&r" (old), "=&r" (t)
|
||||
: "r" (mask), "r" (p)
|
||||
: "cc", "memory");
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
/* This is a special function for mm/filemap.c */
|
||||
#define clear_bit_unlock_is_negative_byte(nr, addr) \
|
||||
(clear_bit_unlock_return_word(nr, addr) & BIT_MASK(PG_waiters))
|
||||
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
#include <asm-generic/bitops/non-atomic.h>
|
||||
|
||||
static __inline__ void __clear_bit_unlock(int nr, volatile unsigned long *addr)
|
||||
|
|
|
@ -57,6 +57,8 @@ struct pnv_php_slot {
|
|||
uint64_t id;
|
||||
char *name;
|
||||
int slot_no;
|
||||
unsigned int flags;
|
||||
#define PNV_PHP_FLAG_BROKEN_PDC 0x1
|
||||
struct kref kref;
|
||||
#define PNV_PHP_STATE_INITIALIZED 0
|
||||
#define PNV_PHP_STATE_REGISTERED 1
|
||||
|
|
|
@ -505,7 +505,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
|
|||
#define MTMSRD(r) mtmsrd r
|
||||
#define MTMSR_EERI(reg) mtmsrd reg,1
|
||||
#else
|
||||
#define FIX_SRR1(ra, rb)
|
||||
#ifndef CONFIG_40x
|
||||
#define RFI rfi
|
||||
#else
|
||||
|
|
|
@ -225,6 +225,7 @@ struct thread_struct {
|
|||
#ifdef CONFIG_PPC64
|
||||
unsigned long start_tb; /* Start purr when proc switched in */
|
||||
unsigned long accum_tb; /* Total accumulated purr for process */
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||
struct perf_event *ptrace_bps[HBP_NUM];
|
||||
/*
|
||||
|
@ -233,7 +234,6 @@ struct thread_struct {
|
|||
*/
|
||||
struct perf_event *last_hit_ubp;
|
||||
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
|
||||
#endif
|
||||
struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */
|
||||
unsigned long trap_nr; /* last trap # on this thread */
|
||||
u8 load_fp;
|
||||
|
|
|
@ -153,6 +153,7 @@ struct of_drconf_cell {
|
|||
#define OV5_XCMO 0x0440 /* Page Coalescing */
|
||||
#define OV5_TYPE1_AFFINITY 0x0580 /* Type 1 NUMA affinity */
|
||||
#define OV5_PRRN 0x0540 /* Platform Resource Reassignment */
|
||||
#define OV5_HP_EVT 0x0604 /* Hot Plug Event support */
|
||||
#define OV5_RESIZE_HPT 0x0601 /* Hash Page Table resizing */
|
||||
#define OV5_PFO_HW_RNG 0x1180 /* PFO Random Number Generator */
|
||||
#define OV5_PFO_HW_842 0x1140 /* PFO Compression Accelerator */
|
||||
|
|
|
@ -552,7 +552,9 @@
|
|||
#define SPRN_IBAT7U 0x236 /* Instruction BAT 7 Upper Register */
|
||||
#define SPRN_ICMP 0x3D5 /* Instruction TLB Compare Register */
|
||||
#define SPRN_ICTC 0x3FB /* Instruction Cache Throttling Control Reg */
|
||||
#ifndef SPRN_ICTRL
|
||||
#define SPRN_ICTRL 0x3F3 /* 1011 7450 icache and interrupt ctrl */
|
||||
#endif
|
||||
#define ICTRL_EICE 0x08000000 /* enable icache parity errs */
|
||||
#define ICTRL_EDC 0x04000000 /* enable dcache parity errs */
|
||||
#define ICTRL_EICP 0x00000100 /* enable icache par. check */
|
||||
|
|
|
@ -28,6 +28,17 @@
|
|||
/* Special MSR manipulation registers */
|
||||
#define SPRN_EIE 80 /* External interrupt enable (EE=1, RI=1) */
|
||||
#define SPRN_EID 81 /* External interrupt disable (EE=0, RI=1) */
|
||||
#define SPRN_NRI 82 /* Non recoverable interrupt (EE=0, RI=0) */
|
||||
|
||||
/* Debug registers */
|
||||
#define SPRN_CMPA 144
|
||||
#define SPRN_COUNTA 150
|
||||
#define SPRN_CMPE 152
|
||||
#define SPRN_CMPF 153
|
||||
#define SPRN_LCTRL1 156
|
||||
#define SPRN_LCTRL2 157
|
||||
#define SPRN_ICTRL 158
|
||||
#define SPRN_BAR 159
|
||||
|
||||
/* Commands. Only the first few are available to the instruction cache.
|
||||
*/
|
||||
|
|
|
@ -307,6 +307,7 @@ struct pseries_hp_errorlog {
|
|||
union {
|
||||
__be32 drc_index;
|
||||
__be32 drc_count;
|
||||
struct { __be32 count, index; } ic;
|
||||
char drc_name[1];
|
||||
} _drc_u;
|
||||
};
|
||||
|
@ -323,6 +324,7 @@ struct pseries_hp_errorlog {
|
|||
#define PSERIES_HP_ELOG_ID_DRC_NAME 1
|
||||
#define PSERIES_HP_ELOG_ID_DRC_INDEX 2
|
||||
#define PSERIES_HP_ELOG_ID_DRC_COUNT 3
|
||||
#define PSERIES_HP_ELOG_ID_DRC_IC 4
|
||||
|
||||
struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
|
||||
uint16_t section_id);
|
||||
|
|
|
@ -72,205 +72,190 @@
|
|||
#include <asm/fixmap.h>
|
||||
#endif
|
||||
|
||||
#define STACK_PT_REGS_OFFSET(sym, val) \
|
||||
DEFINE(sym, STACK_FRAME_OVERHEAD + offsetof(struct pt_regs, val))
|
||||
|
||||
int main(void)
|
||||
{
|
||||
DEFINE(THREAD, offsetof(struct task_struct, thread));
|
||||
DEFINE(MM, offsetof(struct task_struct, mm));
|
||||
DEFINE(MMCONTEXTID, offsetof(struct mm_struct, context.id));
|
||||
OFFSET(THREAD, task_struct, thread);
|
||||
OFFSET(MM, task_struct, mm);
|
||||
OFFSET(MMCONTEXTID, mm_struct, context.id);
|
||||
#ifdef CONFIG_PPC64
|
||||
DEFINE(SIGSEGV, SIGSEGV);
|
||||
DEFINE(NMI_MASK, NMI_MASK);
|
||||
DEFINE(TASKTHREADPPR, offsetof(struct task_struct, thread.ppr));
|
||||
OFFSET(TASKTHREADPPR, task_struct, thread.ppr);
|
||||
#else
|
||||
DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
|
||||
OFFSET(THREAD_INFO, task_struct, stack);
|
||||
DEFINE(THREAD_INFO_GAP, _ALIGN_UP(sizeof(struct thread_info), 16));
|
||||
DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit));
|
||||
OFFSET(KSP_LIMIT, thread_struct, ksp_limit);
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
#ifdef CONFIG_LIVEPATCH
|
||||
DEFINE(TI_livepatch_sp, offsetof(struct thread_info, livepatch_sp));
|
||||
OFFSET(TI_livepatch_sp, thread_info, livepatch_sp);
|
||||
#endif
|
||||
|
||||
DEFINE(KSP, offsetof(struct thread_struct, ksp));
|
||||
DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
|
||||
OFFSET(KSP, thread_struct, ksp);
|
||||
OFFSET(PT_REGS, thread_struct, regs);
|
||||
#ifdef CONFIG_BOOKE
|
||||
DEFINE(THREAD_NORMSAVES, offsetof(struct thread_struct, normsave[0]));
|
||||
OFFSET(THREAD_NORMSAVES, thread_struct, normsave[0]);
|
||||
#endif
|
||||
DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
|
||||
DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fp_state));
|
||||
DEFINE(THREAD_FPSAVEAREA, offsetof(struct thread_struct, fp_save_area));
|
||||
DEFINE(FPSTATE_FPSCR, offsetof(struct thread_fp_state, fpscr));
|
||||
DEFINE(THREAD_LOAD_FP, offsetof(struct thread_struct, load_fp));
|
||||
OFFSET(THREAD_FPEXC_MODE, thread_struct, fpexc_mode);
|
||||
OFFSET(THREAD_FPSTATE, thread_struct, fp_state);
|
||||
OFFSET(THREAD_FPSAVEAREA, thread_struct, fp_save_area);
|
||||
OFFSET(FPSTATE_FPSCR, thread_fp_state, fpscr);
|
||||
OFFSET(THREAD_LOAD_FP, thread_struct, load_fp);
|
||||
#ifdef CONFIG_ALTIVEC
|
||||
DEFINE(THREAD_VRSTATE, offsetof(struct thread_struct, vr_state));
|
||||
DEFINE(THREAD_VRSAVEAREA, offsetof(struct thread_struct, vr_save_area));
|
||||
DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave));
|
||||
DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr));
|
||||
DEFINE(VRSTATE_VSCR, offsetof(struct thread_vr_state, vscr));
|
||||
DEFINE(THREAD_LOAD_VEC, offsetof(struct thread_struct, load_vec));
|
||||
OFFSET(THREAD_VRSTATE, thread_struct, vr_state);
|
||||
OFFSET(THREAD_VRSAVEAREA, thread_struct, vr_save_area);
|
||||
OFFSET(THREAD_VRSAVE, thread_struct, vrsave);
|
||||
OFFSET(THREAD_USED_VR, thread_struct, used_vr);
|
||||
OFFSET(VRSTATE_VSCR, thread_vr_state, vscr);
|
||||
OFFSET(THREAD_LOAD_VEC, thread_struct, load_vec);
|
||||
#endif /* CONFIG_ALTIVEC */
|
||||
#ifdef CONFIG_VSX
|
||||
DEFINE(THREAD_USED_VSR, offsetof(struct thread_struct, used_vsr));
|
||||
OFFSET(THREAD_USED_VSR, thread_struct, used_vsr);
|
||||
#endif /* CONFIG_VSX */
|
||||
#ifdef CONFIG_PPC64
|
||||
DEFINE(KSP_VSID, offsetof(struct thread_struct, ksp_vsid));
|
||||
OFFSET(KSP_VSID, thread_struct, ksp_vsid);
|
||||
#else /* CONFIG_PPC64 */
|
||||
DEFINE(PGDIR, offsetof(struct thread_struct, pgdir));
|
||||
OFFSET(PGDIR, thread_struct, pgdir);
|
||||
#ifdef CONFIG_SPE
|
||||
DEFINE(THREAD_EVR0, offsetof(struct thread_struct, evr[0]));
|
||||
DEFINE(THREAD_ACC, offsetof(struct thread_struct, acc));
|
||||
DEFINE(THREAD_SPEFSCR, offsetof(struct thread_struct, spefscr));
|
||||
DEFINE(THREAD_USED_SPE, offsetof(struct thread_struct, used_spe));
|
||||
OFFSET(THREAD_EVR0, thread_struct, evr[0]);
|
||||
OFFSET(THREAD_ACC, thread_struct, acc);
|
||||
OFFSET(THREAD_SPEFSCR, thread_struct, spefscr);
|
||||
OFFSET(THREAD_USED_SPE, thread_struct, used_spe);
|
||||
#endif /* CONFIG_SPE */
|
||||
#endif /* CONFIG_PPC64 */
|
||||
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
|
||||
DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, debug.dbcr0));
|
||||
OFFSET(THREAD_DBCR0, thread_struct, debug.dbcr0);
|
||||
#endif
|
||||
#ifdef CONFIG_KVM_BOOK3S_32_HANDLER
|
||||
DEFINE(THREAD_KVM_SVCPU, offsetof(struct thread_struct, kvm_shadow_vcpu));
|
||||
OFFSET(THREAD_KVM_SVCPU, thread_struct, kvm_shadow_vcpu);
|
||||
#endif
|
||||
#if defined(CONFIG_KVM) && defined(CONFIG_BOOKE)
|
||||
DEFINE(THREAD_KVM_VCPU, offsetof(struct thread_struct, kvm_vcpu));
|
||||
OFFSET(THREAD_KVM_VCPU, thread_struct, kvm_vcpu);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
DEFINE(PACATMSCRATCH, offsetof(struct paca_struct, tm_scratch));
|
||||
DEFINE(THREAD_TM_TFHAR, offsetof(struct thread_struct, tm_tfhar));
|
||||
DEFINE(THREAD_TM_TEXASR, offsetof(struct thread_struct, tm_texasr));
|
||||
DEFINE(THREAD_TM_TFIAR, offsetof(struct thread_struct, tm_tfiar));
|
||||
DEFINE(THREAD_TM_TAR, offsetof(struct thread_struct, tm_tar));
|
||||
DEFINE(THREAD_TM_PPR, offsetof(struct thread_struct, tm_ppr));
|
||||
DEFINE(THREAD_TM_DSCR, offsetof(struct thread_struct, tm_dscr));
|
||||
DEFINE(PT_CKPT_REGS, offsetof(struct thread_struct, ckpt_regs));
|
||||
DEFINE(THREAD_CKVRSTATE, offsetof(struct thread_struct,
|
||||
ckvr_state));
|
||||
DEFINE(THREAD_CKVRSAVE, offsetof(struct thread_struct,
|
||||
ckvrsave));
|
||||
DEFINE(THREAD_CKFPSTATE, offsetof(struct thread_struct,
|
||||
ckfp_state));
|
||||
OFFSET(PACATMSCRATCH, paca_struct, tm_scratch);
|
||||
OFFSET(THREAD_TM_TFHAR, thread_struct, tm_tfhar);
|
||||
OFFSET(THREAD_TM_TEXASR, thread_struct, tm_texasr);
|
||||
OFFSET(THREAD_TM_TFIAR, thread_struct, tm_tfiar);
|
||||
OFFSET(THREAD_TM_TAR, thread_struct, tm_tar);
|
||||
OFFSET(THREAD_TM_PPR, thread_struct, tm_ppr);
|
||||
OFFSET(THREAD_TM_DSCR, thread_struct, tm_dscr);
|
||||
OFFSET(PT_CKPT_REGS, thread_struct, ckpt_regs);
|
||||
OFFSET(THREAD_CKVRSTATE, thread_struct, ckvr_state);
|
||||
OFFSET(THREAD_CKVRSAVE, thread_struct, ckvrsave);
|
||||
OFFSET(THREAD_CKFPSTATE, thread_struct, ckfp_state);
|
||||
/* Local pt_regs on stack for Transactional Memory funcs. */
|
||||
DEFINE(TM_FRAME_SIZE, STACK_FRAME_OVERHEAD +
|
||||
sizeof(struct pt_regs) + 16);
|
||||
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
|
||||
|
||||
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
|
||||
DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
|
||||
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
|
||||
DEFINE(TI_TASK, offsetof(struct thread_info, task));
|
||||
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
|
||||
OFFSET(TI_FLAGS, thread_info, flags);
|
||||
OFFSET(TI_LOCAL_FLAGS, thread_info, local_flags);
|
||||
OFFSET(TI_PREEMPT, thread_info, preempt_count);
|
||||
OFFSET(TI_TASK, thread_info, task);
|
||||
OFFSET(TI_CPU, thread_info, cpu);
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
DEFINE(DCACHEL1BLOCKSIZE, offsetof(struct ppc64_caches, l1d.block_size));
|
||||
DEFINE(DCACHEL1LOGBLOCKSIZE, offsetof(struct ppc64_caches, l1d.log_block_size));
|
||||
DEFINE(DCACHEL1BLOCKSPERPAGE, offsetof(struct ppc64_caches, l1d.blocks_per_page));
|
||||
DEFINE(ICACHEL1BLOCKSIZE, offsetof(struct ppc64_caches, l1i.block_size));
|
||||
DEFINE(ICACHEL1LOGBLOCKSIZE, offsetof(struct ppc64_caches, l1i.log_block_size));
|
||||
DEFINE(ICACHEL1BLOCKSPERPAGE, offsetof(struct ppc64_caches, l1i.blocks_per_page));
|
||||
OFFSET(DCACHEL1BLOCKSIZE, ppc64_caches, l1d.block_size);
|
||||
OFFSET(DCACHEL1LOGBLOCKSIZE, ppc64_caches, l1d.log_block_size);
|
||||
OFFSET(DCACHEL1BLOCKSPERPAGE, ppc64_caches, l1d.blocks_per_page);
|
||||
OFFSET(ICACHEL1BLOCKSIZE, ppc64_caches, l1i.block_size);
|
||||
OFFSET(ICACHEL1LOGBLOCKSIZE, ppc64_caches, l1i.log_block_size);
|
||||
OFFSET(ICACHEL1BLOCKSPERPAGE, ppc64_caches, l1i.blocks_per_page);
|
||||
/* paca */
|
||||
DEFINE(PACA_SIZE, sizeof(struct paca_struct));
|
||||
DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index));
|
||||
DEFINE(PACAPROCSTART, offsetof(struct paca_struct, cpu_start));
|
||||
DEFINE(PACAKSAVE, offsetof(struct paca_struct, kstack));
|
||||
DEFINE(PACACURRENT, offsetof(struct paca_struct, __current));
|
||||
DEFINE(PACASAVEDMSR, offsetof(struct paca_struct, saved_msr));
|
||||
DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr));
|
||||
DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1));
|
||||
DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc));
|
||||
DEFINE(PACAKBASE, offsetof(struct paca_struct, kernelbase));
|
||||
DEFINE(PACAKMSR, offsetof(struct paca_struct, kernel_msr));
|
||||
DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled));
|
||||
DEFINE(PACAIRQHAPPENED, offsetof(struct paca_struct, irq_happened));
|
||||
OFFSET(PACAPACAINDEX, paca_struct, paca_index);
|
||||
OFFSET(PACAPROCSTART, paca_struct, cpu_start);
|
||||
OFFSET(PACAKSAVE, paca_struct, kstack);
|
||||
OFFSET(PACACURRENT, paca_struct, __current);
|
||||
OFFSET(PACASAVEDMSR, paca_struct, saved_msr);
|
||||
OFFSET(PACASTABRR, paca_struct, stab_rr);
|
||||
OFFSET(PACAR1, paca_struct, saved_r1);
|
||||
OFFSET(PACATOC, paca_struct, kernel_toc);
|
||||
OFFSET(PACAKBASE, paca_struct, kernelbase);
|
||||
OFFSET(PACAKMSR, paca_struct, kernel_msr);
|
||||
OFFSET(PACASOFTIRQEN, paca_struct, soft_enabled);
|
||||
OFFSET(PACAIRQHAPPENED, paca_struct, irq_happened);
|
||||
#ifdef CONFIG_PPC_BOOK3S
|
||||
DEFINE(PACACONTEXTID, offsetof(struct paca_struct, mm_ctx_id));
|
||||
OFFSET(PACACONTEXTID, paca_struct, mm_ctx_id);
|
||||
#ifdef CONFIG_PPC_MM_SLICES
|
||||
DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct,
|
||||
mm_ctx_low_slices_psize));
|
||||
DEFINE(PACAHIGHSLICEPSIZE, offsetof(struct paca_struct,
|
||||
mm_ctx_high_slices_psize));
|
||||
OFFSET(PACALOWSLICESPSIZE, paca_struct, mm_ctx_low_slices_psize);
|
||||
OFFSET(PACAHIGHSLICEPSIZE, paca_struct, mm_ctx_high_slices_psize);
|
||||
DEFINE(MMUPSIZEDEFSIZE, sizeof(struct mmu_psize_def));
|
||||
#endif /* CONFIG_PPC_MM_SLICES */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
DEFINE(PACAPGD, offsetof(struct paca_struct, pgd));
|
||||
DEFINE(PACA_KERNELPGD, offsetof(struct paca_struct, kernel_pgd));
|
||||
DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen));
|
||||
DEFINE(PACA_EXTLB, offsetof(struct paca_struct, extlb));
|
||||
DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc));
|
||||
DEFINE(PACA_EXCRIT, offsetof(struct paca_struct, excrit));
|
||||
DEFINE(PACA_EXDBG, offsetof(struct paca_struct, exdbg));
|
||||
DEFINE(PACA_MC_STACK, offsetof(struct paca_struct, mc_kstack));
|
||||
DEFINE(PACA_CRIT_STACK, offsetof(struct paca_struct, crit_kstack));
|
||||
DEFINE(PACA_DBG_STACK, offsetof(struct paca_struct, dbg_kstack));
|
||||
DEFINE(PACA_TCD_PTR, offsetof(struct paca_struct, tcd_ptr));
|
||||
OFFSET(PACAPGD, paca_struct, pgd);
|
||||
OFFSET(PACA_KERNELPGD, paca_struct, kernel_pgd);
|
||||
OFFSET(PACA_EXGEN, paca_struct, exgen);
|
||||
OFFSET(PACA_EXTLB, paca_struct, extlb);
|
||||
OFFSET(PACA_EXMC, paca_struct, exmc);
|
||||
OFFSET(PACA_EXCRIT, paca_struct, excrit);
|
||||
OFFSET(PACA_EXDBG, paca_struct, exdbg);
|
||||
OFFSET(PACA_MC_STACK, paca_struct, mc_kstack);
|
||||
OFFSET(PACA_CRIT_STACK, paca_struct, crit_kstack);
|
||||
OFFSET(PACA_DBG_STACK, paca_struct, dbg_kstack);
|
||||
OFFSET(PACA_TCD_PTR, paca_struct, tcd_ptr);
|
||||
|
||||
DEFINE(TCD_ESEL_NEXT,
|
||||
offsetof(struct tlb_core_data, esel_next));
|
||||
DEFINE(TCD_ESEL_MAX,
|
||||
offsetof(struct tlb_core_data, esel_max));
|
||||
DEFINE(TCD_ESEL_FIRST,
|
||||
offsetof(struct tlb_core_data, esel_first));
|
||||
OFFSET(TCD_ESEL_NEXT, tlb_core_data, esel_next);
|
||||
OFFSET(TCD_ESEL_MAX, tlb_core_data, esel_max);
|
||||
OFFSET(TCD_ESEL_FIRST, tlb_core_data, esel_first);
|
||||
#endif /* CONFIG_PPC_BOOK3E */
|
||||
|
||||
#ifdef CONFIG_PPC_STD_MMU_64
|
||||
DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
|
||||
DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
|
||||
DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp));
|
||||
OFFSET(PACASLBCACHE, paca_struct, slb_cache);
|
||||
OFFSET(PACASLBCACHEPTR, paca_struct, slb_cache_ptr);
|
||||
OFFSET(PACAVMALLOCSLLP, paca_struct, vmalloc_sllp);
|
||||
#ifdef CONFIG_PPC_MM_SLICES
|
||||
DEFINE(MMUPSIZESLLP, offsetof(struct mmu_psize_def, sllp));
|
||||
OFFSET(MMUPSIZESLLP, mmu_psize_def, sllp);
|
||||
#else
|
||||
DEFINE(PACACONTEXTSLLP, offsetof(struct paca_struct, mm_ctx_sllp));
|
||||
OFFSET(PACACONTEXTSLLP, paca_struct, mm_ctx_sllp);
|
||||
#endif /* CONFIG_PPC_MM_SLICES */
|
||||
DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen));
|
||||
DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc));
|
||||
DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb));
|
||||
DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr));
|
||||
DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr));
|
||||
DEFINE(SLBSHADOW_STACKVSID,
|
||||
offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid));
|
||||
DEFINE(SLBSHADOW_STACKESID,
|
||||
offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].esid));
|
||||
DEFINE(SLBSHADOW_SAVEAREA, offsetof(struct slb_shadow, save_area));
|
||||
DEFINE(LPPACA_PMCINUSE, offsetof(struct lppaca, pmcregs_in_use));
|
||||
DEFINE(LPPACA_DTLIDX, offsetof(struct lppaca, dtl_idx));
|
||||
DEFINE(LPPACA_YIELDCOUNT, offsetof(struct lppaca, yield_count));
|
||||
DEFINE(PACA_DTL_RIDX, offsetof(struct paca_struct, dtl_ridx));
|
||||
OFFSET(PACA_EXGEN, paca_struct, exgen);
|
||||
OFFSET(PACA_EXMC, paca_struct, exmc);
|
||||
OFFSET(PACA_EXSLB, paca_struct, exslb);
|
||||
OFFSET(PACALPPACAPTR, paca_struct, lppaca_ptr);
|
||||
OFFSET(PACA_SLBSHADOWPTR, paca_struct, slb_shadow_ptr);
|
||||
OFFSET(SLBSHADOW_STACKVSID, slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid);
|
||||
OFFSET(SLBSHADOW_STACKESID, slb_shadow, save_area[SLB_NUM_BOLTED - 1].esid);
|
||||
OFFSET(SLBSHADOW_SAVEAREA, slb_shadow, save_area);
|
||||
OFFSET(LPPACA_PMCINUSE, lppaca, pmcregs_in_use);
|
||||
OFFSET(LPPACA_DTLIDX, lppaca, dtl_idx);
|
||||
OFFSET(LPPACA_YIELDCOUNT, lppaca, yield_count);
|
||||
OFFSET(PACA_DTL_RIDX, paca_struct, dtl_ridx);
|
||||
#endif /* CONFIG_PPC_STD_MMU_64 */
|
||||
DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
|
||||
OFFSET(PACAEMERGSP, paca_struct, emergency_sp);
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
DEFINE(PACAMCEMERGSP, offsetof(struct paca_struct, mc_emergency_sp));
|
||||
DEFINE(PACA_IN_MCE, offsetof(struct paca_struct, in_mce));
|
||||
OFFSET(PACAMCEMERGSP, paca_struct, mc_emergency_sp);
|
||||
OFFSET(PACA_IN_MCE, paca_struct, in_mce);
|
||||
#endif
|
||||
DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
|
||||
DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state));
|
||||
DEFINE(PACA_DSCR_DEFAULT, offsetof(struct paca_struct, dscr_default));
|
||||
DEFINE(ACCOUNT_STARTTIME,
|
||||
offsetof(struct paca_struct, accounting.starttime));
|
||||
DEFINE(ACCOUNT_STARTTIME_USER,
|
||||
offsetof(struct paca_struct, accounting.starttime_user));
|
||||
DEFINE(ACCOUNT_USER_TIME,
|
||||
offsetof(struct paca_struct, accounting.utime));
|
||||
DEFINE(ACCOUNT_SYSTEM_TIME,
|
||||
offsetof(struct paca_struct, accounting.stime));
|
||||
DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
|
||||
DEFINE(PACA_NAPSTATELOST, offsetof(struct paca_struct, nap_state_lost));
|
||||
DEFINE(PACA_SPRG_VDSO, offsetof(struct paca_struct, sprg_vdso));
|
||||
OFFSET(PACAHWCPUID, paca_struct, hw_cpu_id);
|
||||
OFFSET(PACAKEXECSTATE, paca_struct, kexec_state);
|
||||
OFFSET(PACA_DSCR_DEFAULT, paca_struct, dscr_default);
|
||||
OFFSET(ACCOUNT_STARTTIME, paca_struct, accounting.starttime);
|
||||
OFFSET(ACCOUNT_STARTTIME_USER, paca_struct, accounting.starttime_user);
|
||||
OFFSET(ACCOUNT_USER_TIME, paca_struct, accounting.utime);
|
||||
OFFSET(ACCOUNT_SYSTEM_TIME, paca_struct, accounting.stime);
|
||||
OFFSET(PACA_TRAP_SAVE, paca_struct, trap_save);
|
||||
OFFSET(PACA_NAPSTATELOST, paca_struct, nap_state_lost);
|
||||
OFFSET(PACA_SPRG_VDSO, paca_struct, sprg_vdso);
|
||||
#else /* CONFIG_PPC64 */
|
||||
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
|
||||
DEFINE(ACCOUNT_STARTTIME,
|
||||
offsetof(struct thread_info, accounting.starttime));
|
||||
DEFINE(ACCOUNT_STARTTIME_USER,
|
||||
offsetof(struct thread_info, accounting.starttime_user));
|
||||
DEFINE(ACCOUNT_USER_TIME,
|
||||
offsetof(struct thread_info, accounting.utime));
|
||||
DEFINE(ACCOUNT_SYSTEM_TIME,
|
||||
offsetof(struct thread_info, accounting.stime));
|
||||
OFFSET(ACCOUNT_STARTTIME, thread_info, accounting.starttime);
|
||||
OFFSET(ACCOUNT_STARTTIME_USER, thread_info, accounting.starttime_user);
|
||||
OFFSET(ACCOUNT_USER_TIME, thread_info, accounting.utime);
|
||||
OFFSET(ACCOUNT_SYSTEM_TIME, thread_info, accounting.stime);
|
||||
#endif
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
/* RTAS */
|
||||
DEFINE(RTASBASE, offsetof(struct rtas_t, base));
|
||||
DEFINE(RTASENTRY, offsetof(struct rtas_t, entry));
|
||||
OFFSET(RTASBASE, rtas_t, base);
|
||||
OFFSET(RTASENTRY, rtas_t, entry);
|
||||
|
||||
/* Interrupt register frame */
|
||||
DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE);
|
||||
|
@ -280,38 +265,38 @@ int main(void)
|
|||
DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
|
||||
DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
|
||||
#endif /* CONFIG_PPC64 */
|
||||
DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0]));
|
||||
DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1]));
|
||||
DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2]));
|
||||
DEFINE(GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[3]));
|
||||
DEFINE(GPR4, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[4]));
|
||||
DEFINE(GPR5, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[5]));
|
||||
DEFINE(GPR6, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[6]));
|
||||
DEFINE(GPR7, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[7]));
|
||||
DEFINE(GPR8, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[8]));
|
||||
DEFINE(GPR9, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[9]));
|
||||
DEFINE(GPR10, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[10]));
|
||||
DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11]));
|
||||
DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12]));
|
||||
DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13]));
|
||||
STACK_PT_REGS_OFFSET(GPR0, gpr[0]);
|
||||
STACK_PT_REGS_OFFSET(GPR1, gpr[1]);
|
||||
STACK_PT_REGS_OFFSET(GPR2, gpr[2]);
|
||||
STACK_PT_REGS_OFFSET(GPR3, gpr[3]);
|
||||
STACK_PT_REGS_OFFSET(GPR4, gpr[4]);
|
||||
STACK_PT_REGS_OFFSET(GPR5, gpr[5]);
|
||||
STACK_PT_REGS_OFFSET(GPR6, gpr[6]);
|
||||
STACK_PT_REGS_OFFSET(GPR7, gpr[7]);
|
||||
STACK_PT_REGS_OFFSET(GPR8, gpr[8]);
|
||||
STACK_PT_REGS_OFFSET(GPR9, gpr[9]);
|
||||
STACK_PT_REGS_OFFSET(GPR10, gpr[10]);
|
||||
STACK_PT_REGS_OFFSET(GPR11, gpr[11]);
|
||||
STACK_PT_REGS_OFFSET(GPR12, gpr[12]);
|
||||
STACK_PT_REGS_OFFSET(GPR13, gpr[13]);
|
||||
#ifndef CONFIG_PPC64
|
||||
DEFINE(GPR14, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[14]));
|
||||
STACK_PT_REGS_OFFSET(GPR14, gpr[14]);
|
||||
#endif /* CONFIG_PPC64 */
|
||||
/*
|
||||
* Note: these symbols include _ because they overlap with special
|
||||
* register names
|
||||
*/
|
||||
DEFINE(_NIP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, nip));
|
||||
DEFINE(_MSR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, msr));
|
||||
DEFINE(_CTR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ctr));
|
||||
DEFINE(_LINK, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, link));
|
||||
DEFINE(_CCR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ccr));
|
||||
DEFINE(_XER, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, xer));
|
||||
DEFINE(_DAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar));
|
||||
DEFINE(_DSISR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr));
|
||||
DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3));
|
||||
DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result));
|
||||
DEFINE(_TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap));
|
||||
STACK_PT_REGS_OFFSET(_NIP, nip);
|
||||
STACK_PT_REGS_OFFSET(_MSR, msr);
|
||||
STACK_PT_REGS_OFFSET(_CTR, ctr);
|
||||
STACK_PT_REGS_OFFSET(_LINK, link);
|
||||
STACK_PT_REGS_OFFSET(_CCR, ccr);
|
||||
STACK_PT_REGS_OFFSET(_XER, xer);
|
||||
STACK_PT_REGS_OFFSET(_DAR, dar);
|
||||
STACK_PT_REGS_OFFSET(_DSISR, dsisr);
|
||||
STACK_PT_REGS_OFFSET(ORIG_GPR3, orig_gpr3);
|
||||
STACK_PT_REGS_OFFSET(RESULT, result);
|
||||
STACK_PT_REGS_OFFSET(_TRAP, trap);
|
||||
#ifndef CONFIG_PPC64
|
||||
/*
|
||||
* The PowerPC 400-class & Book-E processors have neither the DAR
|
||||
|
@ -319,10 +304,10 @@ int main(void)
|
|||
* DEAR and ESR SPRs for such processors. For critical interrupts
|
||||
* we use them to hold SRR0 and SRR1.
|
||||
*/
|
||||
DEFINE(_DEAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar));
|
||||
DEFINE(_ESR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr));
|
||||
STACK_PT_REGS_OFFSET(_DEAR, dar);
|
||||
STACK_PT_REGS_OFFSET(_ESR, dsisr);
|
||||
#else /* CONFIG_PPC64 */
|
||||
DEFINE(SOFTE, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, softe));
|
||||
STACK_PT_REGS_OFFSET(SOFTE, softe);
|
||||
|
||||
/* These _only_ to be used with {PROM,RTAS}_FRAME_SIZE!!! */
|
||||
DEFINE(_SRR0, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs));
|
||||
|
@ -351,17 +336,17 @@ int main(void)
|
|||
#endif
|
||||
|
||||
#ifndef CONFIG_PPC64
|
||||
DEFINE(MM_PGD, offsetof(struct mm_struct, pgd));
|
||||
OFFSET(MM_PGD, mm_struct, pgd);
|
||||
#endif /* ! CONFIG_PPC64 */
|
||||
|
||||
/* About the CPU features table */
|
||||
DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
|
||||
DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
|
||||
DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore));
|
||||
OFFSET(CPU_SPEC_FEATURES, cpu_spec, cpu_features);
|
||||
OFFSET(CPU_SPEC_SETUP, cpu_spec, cpu_setup);
|
||||
OFFSET(CPU_SPEC_RESTORE, cpu_spec, cpu_restore);
|
||||
|
||||
DEFINE(pbe_address, offsetof(struct pbe, address));
|
||||
DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
|
||||
DEFINE(pbe_next, offsetof(struct pbe, next));
|
||||
OFFSET(pbe_address, pbe, address);
|
||||
OFFSET(pbe_orig_address, pbe, orig_address);
|
||||
OFFSET(pbe_next, pbe, next);
|
||||
|
||||
#ifndef CONFIG_PPC64
|
||||
DEFINE(TASK_SIZE, TASK_SIZE);
|
||||
|
@ -369,40 +354,40 @@ int main(void)
|
|||
#endif /* ! CONFIG_PPC64 */
|
||||
|
||||
/* datapage offsets for use by vdso */
|
||||
DEFINE(CFG_TB_ORIG_STAMP, offsetof(struct vdso_data, tb_orig_stamp));
|
||||
DEFINE(CFG_TB_TICKS_PER_SEC, offsetof(struct vdso_data, tb_ticks_per_sec));
|
||||
DEFINE(CFG_TB_TO_XS, offsetof(struct vdso_data, tb_to_xs));
|
||||
DEFINE(CFG_TB_UPDATE_COUNT, offsetof(struct vdso_data, tb_update_count));
|
||||
DEFINE(CFG_TZ_MINUTEWEST, offsetof(struct vdso_data, tz_minuteswest));
|
||||
DEFINE(CFG_TZ_DSTTIME, offsetof(struct vdso_data, tz_dsttime));
|
||||
DEFINE(CFG_SYSCALL_MAP32, offsetof(struct vdso_data, syscall_map_32));
|
||||
DEFINE(WTOM_CLOCK_SEC, offsetof(struct vdso_data, wtom_clock_sec));
|
||||
DEFINE(WTOM_CLOCK_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
|
||||
DEFINE(STAMP_XTIME, offsetof(struct vdso_data, stamp_xtime));
|
||||
DEFINE(STAMP_SEC_FRAC, offsetof(struct vdso_data, stamp_sec_fraction));
|
||||
DEFINE(CFG_ICACHE_BLOCKSZ, offsetof(struct vdso_data, icache_block_size));
|
||||
DEFINE(CFG_DCACHE_BLOCKSZ, offsetof(struct vdso_data, dcache_block_size));
|
||||
DEFINE(CFG_ICACHE_LOGBLOCKSZ, offsetof(struct vdso_data, icache_log_block_size));
|
||||
DEFINE(CFG_DCACHE_LOGBLOCKSZ, offsetof(struct vdso_data, dcache_log_block_size));
|
||||
OFFSET(CFG_TB_ORIG_STAMP, vdso_data, tb_orig_stamp);
|
||||
OFFSET(CFG_TB_TICKS_PER_SEC, vdso_data, tb_ticks_per_sec);
|
||||
OFFSET(CFG_TB_TO_XS, vdso_data, tb_to_xs);
|
||||
OFFSET(CFG_TB_UPDATE_COUNT, vdso_data, tb_update_count);
|
||||
OFFSET(CFG_TZ_MINUTEWEST, vdso_data, tz_minuteswest);
|
||||
OFFSET(CFG_TZ_DSTTIME, vdso_data, tz_dsttime);
|
||||
OFFSET(CFG_SYSCALL_MAP32, vdso_data, syscall_map_32);
|
||||
OFFSET(WTOM_CLOCK_SEC, vdso_data, wtom_clock_sec);
|
||||
OFFSET(WTOM_CLOCK_NSEC, vdso_data, wtom_clock_nsec);
|
||||
OFFSET(STAMP_XTIME, vdso_data, stamp_xtime);
|
||||
OFFSET(STAMP_SEC_FRAC, vdso_data, stamp_sec_fraction);
|
||||
OFFSET(CFG_ICACHE_BLOCKSZ, vdso_data, icache_block_size);
|
||||
OFFSET(CFG_DCACHE_BLOCKSZ, vdso_data, dcache_block_size);
|
||||
OFFSET(CFG_ICACHE_LOGBLOCKSZ, vdso_data, icache_log_block_size);
|
||||
OFFSET(CFG_DCACHE_LOGBLOCKSZ, vdso_data, dcache_log_block_size);
|
||||
#ifdef CONFIG_PPC64
|
||||
DEFINE(CFG_SYSCALL_MAP64, offsetof(struct vdso_data, syscall_map_64));
|
||||
DEFINE(TVAL64_TV_SEC, offsetof(struct timeval, tv_sec));
|
||||
DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec));
|
||||
DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec));
|
||||
DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec));
|
||||
DEFINE(TSPC64_TV_SEC, offsetof(struct timespec, tv_sec));
|
||||
DEFINE(TSPC64_TV_NSEC, offsetof(struct timespec, tv_nsec));
|
||||
DEFINE(TSPC32_TV_SEC, offsetof(struct compat_timespec, tv_sec));
|
||||
DEFINE(TSPC32_TV_NSEC, offsetof(struct compat_timespec, tv_nsec));
|
||||
OFFSET(CFG_SYSCALL_MAP64, vdso_data, syscall_map_64);
|
||||
OFFSET(TVAL64_TV_SEC, timeval, tv_sec);
|
||||
OFFSET(TVAL64_TV_USEC, timeval, tv_usec);
|
||||
OFFSET(TVAL32_TV_SEC, compat_timeval, tv_sec);
|
||||
OFFSET(TVAL32_TV_USEC, compat_timeval, tv_usec);
|
||||
OFFSET(TSPC64_TV_SEC, timespec, tv_sec);
|
||||
OFFSET(TSPC64_TV_NSEC, timespec, tv_nsec);
|
||||
OFFSET(TSPC32_TV_SEC, compat_timespec, tv_sec);
|
||||
OFFSET(TSPC32_TV_NSEC, compat_timespec, tv_nsec);
|
||||
#else
|
||||
DEFINE(TVAL32_TV_SEC, offsetof(struct timeval, tv_sec));
|
||||
DEFINE(TVAL32_TV_USEC, offsetof(struct timeval, tv_usec));
|
||||
DEFINE(TSPC32_TV_SEC, offsetof(struct timespec, tv_sec));
|
||||
DEFINE(TSPC32_TV_NSEC, offsetof(struct timespec, tv_nsec));
|
||||
OFFSET(TVAL32_TV_SEC, timeval, tv_sec);
|
||||
OFFSET(TVAL32_TV_USEC, timeval, tv_usec);
|
||||
OFFSET(TSPC32_TV_SEC, timespec, tv_sec);
|
||||
OFFSET(TSPC32_TV_NSEC, timespec, tv_nsec);
|
||||
#endif
|
||||
/* timeval/timezone offsets for use by vdso */
|
||||
DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest));
|
||||
DEFINE(TZONE_TZ_DSTTIME, offsetof(struct timezone, tz_dsttime));
|
||||
OFFSET(TZONE_TZ_MINWEST, timezone, tz_minuteswest);
|
||||
OFFSET(TZONE_TZ_DSTTIME, timezone, tz_dsttime);
|
||||
|
||||
/* Other bits used by the vdso */
|
||||
DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
|
||||
|
@ -422,170 +407,170 @@ int main(void)
|
|||
DEFINE(PTE_SIZE, sizeof(pte_t));
|
||||
|
||||
#ifdef CONFIG_KVM
|
||||
DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack));
|
||||
DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid));
|
||||
DEFINE(VCPU_GUEST_PID, offsetof(struct kvm_vcpu, arch.pid));
|
||||
DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
|
||||
DEFINE(VCPU_VRSAVE, offsetof(struct kvm_vcpu, arch.vrsave));
|
||||
DEFINE(VCPU_FPRS, offsetof(struct kvm_vcpu, arch.fp.fpr));
|
||||
OFFSET(VCPU_HOST_STACK, kvm_vcpu, arch.host_stack);
|
||||
OFFSET(VCPU_HOST_PID, kvm_vcpu, arch.host_pid);
|
||||
OFFSET(VCPU_GUEST_PID, kvm_vcpu, arch.pid);
|
||||
OFFSET(VCPU_GPRS, kvm_vcpu, arch.gpr);
|
||||
OFFSET(VCPU_VRSAVE, kvm_vcpu, arch.vrsave);
|
||||
OFFSET(VCPU_FPRS, kvm_vcpu, arch.fp.fpr);
|
||||
#ifdef CONFIG_ALTIVEC
|
||||
DEFINE(VCPU_VRS, offsetof(struct kvm_vcpu, arch.vr.vr));
|
||||
OFFSET(VCPU_VRS, kvm_vcpu, arch.vr.vr);
|
||||
#endif
|
||||
DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
|
||||
DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
|
||||
DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
|
||||
OFFSET(VCPU_XER, kvm_vcpu, arch.xer);
|
||||
OFFSET(VCPU_CTR, kvm_vcpu, arch.ctr);
|
||||
OFFSET(VCPU_LR, kvm_vcpu, arch.lr);
|
||||
#ifdef CONFIG_PPC_BOOK3S
|
||||
DEFINE(VCPU_TAR, offsetof(struct kvm_vcpu, arch.tar));
|
||||
OFFSET(VCPU_TAR, kvm_vcpu, arch.tar);
|
||||
#endif
|
||||
DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
|
||||
DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc));
|
||||
OFFSET(VCPU_CR, kvm_vcpu, arch.cr);
|
||||
OFFSET(VCPU_PC, kvm_vcpu, arch.pc);
|
||||
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
|
||||
DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.shregs.msr));
|
||||
DEFINE(VCPU_SRR0, offsetof(struct kvm_vcpu, arch.shregs.srr0));
|
||||
DEFINE(VCPU_SRR1, offsetof(struct kvm_vcpu, arch.shregs.srr1));
|
||||
DEFINE(VCPU_SPRG0, offsetof(struct kvm_vcpu, arch.shregs.sprg0));
|
||||
DEFINE(VCPU_SPRG1, offsetof(struct kvm_vcpu, arch.shregs.sprg1));
|
||||
DEFINE(VCPU_SPRG2, offsetof(struct kvm_vcpu, arch.shregs.sprg2));
|
||||
DEFINE(VCPU_SPRG3, offsetof(struct kvm_vcpu, arch.shregs.sprg3));
|
||||
OFFSET(VCPU_MSR, kvm_vcpu, arch.shregs.msr);
|
||||
OFFSET(VCPU_SRR0, kvm_vcpu, arch.shregs.srr0);
|
||||
OFFSET(VCPU_SRR1, kvm_vcpu, arch.shregs.srr1);
|
||||
OFFSET(VCPU_SPRG0, kvm_vcpu, arch.shregs.sprg0);
|
||||
OFFSET(VCPU_SPRG1, kvm_vcpu, arch.shregs.sprg1);
|
||||
OFFSET(VCPU_SPRG2, kvm_vcpu, arch.shregs.sprg2);
|
||||
OFFSET(VCPU_SPRG3, kvm_vcpu, arch.shregs.sprg3);
|
||||
#endif
|
||||
#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
|
||||
DEFINE(VCPU_TB_RMENTRY, offsetof(struct kvm_vcpu, arch.rm_entry));
|
||||
DEFINE(VCPU_TB_RMINTR, offsetof(struct kvm_vcpu, arch.rm_intr));
|
||||
DEFINE(VCPU_TB_RMEXIT, offsetof(struct kvm_vcpu, arch.rm_exit));
|
||||
DEFINE(VCPU_TB_GUEST, offsetof(struct kvm_vcpu, arch.guest_time));
|
||||
DEFINE(VCPU_TB_CEDE, offsetof(struct kvm_vcpu, arch.cede_time));
|
||||
DEFINE(VCPU_CUR_ACTIVITY, offsetof(struct kvm_vcpu, arch.cur_activity));
|
||||
DEFINE(VCPU_ACTIVITY_START, offsetof(struct kvm_vcpu, arch.cur_tb_start));
|
||||
DEFINE(TAS_SEQCOUNT, offsetof(struct kvmhv_tb_accumulator, seqcount));
|
||||
DEFINE(TAS_TOTAL, offsetof(struct kvmhv_tb_accumulator, tb_total));
|
||||
DEFINE(TAS_MIN, offsetof(struct kvmhv_tb_accumulator, tb_min));
|
||||
DEFINE(TAS_MAX, offsetof(struct kvmhv_tb_accumulator, tb_max));
|
||||
OFFSET(VCPU_TB_RMENTRY, kvm_vcpu, arch.rm_entry);
|
||||
OFFSET(VCPU_TB_RMINTR, kvm_vcpu, arch.rm_intr);
|
||||
OFFSET(VCPU_TB_RMEXIT, kvm_vcpu, arch.rm_exit);
|
||||
OFFSET(VCPU_TB_GUEST, kvm_vcpu, arch.guest_time);
|
||||
OFFSET(VCPU_TB_CEDE, kvm_vcpu, arch.cede_time);
|
||||
OFFSET(VCPU_CUR_ACTIVITY, kvm_vcpu, arch.cur_activity);
|
||||
OFFSET(VCPU_ACTIVITY_START, kvm_vcpu, arch.cur_tb_start);
|
||||
OFFSET(TAS_SEQCOUNT, kvmhv_tb_accumulator, seqcount);
|
||||
OFFSET(TAS_TOTAL, kvmhv_tb_accumulator, tb_total);
|
||||
OFFSET(TAS_MIN, kvmhv_tb_accumulator, tb_min);
|
||||
OFFSET(TAS_MAX, kvmhv_tb_accumulator, tb_max);
|
||||
#endif
|
||||
DEFINE(VCPU_SHARED_SPRG3, offsetof(struct kvm_vcpu_arch_shared, sprg3));
|
||||
DEFINE(VCPU_SHARED_SPRG4, offsetof(struct kvm_vcpu_arch_shared, sprg4));
|
||||
DEFINE(VCPU_SHARED_SPRG5, offsetof(struct kvm_vcpu_arch_shared, sprg5));
|
||||
DEFINE(VCPU_SHARED_SPRG6, offsetof(struct kvm_vcpu_arch_shared, sprg6));
|
||||
DEFINE(VCPU_SHARED_SPRG7, offsetof(struct kvm_vcpu_arch_shared, sprg7));
|
||||
DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid));
|
||||
DEFINE(VCPU_SHADOW_PID1, offsetof(struct kvm_vcpu, arch.shadow_pid1));
|
||||
DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared));
|
||||
DEFINE(VCPU_SHARED_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
|
||||
DEFINE(VCPU_SHADOW_MSR, offsetof(struct kvm_vcpu, arch.shadow_msr));
|
||||
OFFSET(VCPU_SHARED_SPRG3, kvm_vcpu_arch_shared, sprg3);
|
||||
OFFSET(VCPU_SHARED_SPRG4, kvm_vcpu_arch_shared, sprg4);
|
||||
OFFSET(VCPU_SHARED_SPRG5, kvm_vcpu_arch_shared, sprg5);
|
||||
OFFSET(VCPU_SHARED_SPRG6, kvm_vcpu_arch_shared, sprg6);
|
||||
OFFSET(VCPU_SHARED_SPRG7, kvm_vcpu_arch_shared, sprg7);
|
||||
OFFSET(VCPU_SHADOW_PID, kvm_vcpu, arch.shadow_pid);
|
||||
OFFSET(VCPU_SHADOW_PID1, kvm_vcpu, arch.shadow_pid1);
|
||||
OFFSET(VCPU_SHARED, kvm_vcpu, arch.shared);
|
||||
OFFSET(VCPU_SHARED_MSR, kvm_vcpu_arch_shared, msr);
|
||||
OFFSET(VCPU_SHADOW_MSR, kvm_vcpu, arch.shadow_msr);
|
||||
#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_KVM_BOOK3S_PR_POSSIBLE)
|
||||
DEFINE(VCPU_SHAREDBE, offsetof(struct kvm_vcpu, arch.shared_big_endian));
|
||||
OFFSET(VCPU_SHAREDBE, kvm_vcpu, arch.shared_big_endian);
|
||||
#endif
|
||||
|
||||
DEFINE(VCPU_SHARED_MAS0, offsetof(struct kvm_vcpu_arch_shared, mas0));
|
||||
DEFINE(VCPU_SHARED_MAS1, offsetof(struct kvm_vcpu_arch_shared, mas1));
|
||||
DEFINE(VCPU_SHARED_MAS2, offsetof(struct kvm_vcpu_arch_shared, mas2));
|
||||
DEFINE(VCPU_SHARED_MAS7_3, offsetof(struct kvm_vcpu_arch_shared, mas7_3));
|
||||
DEFINE(VCPU_SHARED_MAS4, offsetof(struct kvm_vcpu_arch_shared, mas4));
|
||||
DEFINE(VCPU_SHARED_MAS6, offsetof(struct kvm_vcpu_arch_shared, mas6));
|
||||
OFFSET(VCPU_SHARED_MAS0, kvm_vcpu_arch_shared, mas0);
|
||||
OFFSET(VCPU_SHARED_MAS1, kvm_vcpu_arch_shared, mas1);
|
||||
OFFSET(VCPU_SHARED_MAS2, kvm_vcpu_arch_shared, mas2);
|
||||
OFFSET(VCPU_SHARED_MAS7_3, kvm_vcpu_arch_shared, mas7_3);
|
||||
OFFSET(VCPU_SHARED_MAS4, kvm_vcpu_arch_shared, mas4);
|
||||
OFFSET(VCPU_SHARED_MAS6, kvm_vcpu_arch_shared, mas6);
|
||||
|
||||
DEFINE(VCPU_KVM, offsetof(struct kvm_vcpu, kvm));
|
||||
DEFINE(KVM_LPID, offsetof(struct kvm, arch.lpid));
|
||||
OFFSET(VCPU_KVM, kvm_vcpu, kvm);
|
||||
OFFSET(KVM_LPID, kvm, arch.lpid);
|
||||
|
||||
/* book3s */
|
||||
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
|
||||
DEFINE(KVM_TLB_SETS, offsetof(struct kvm, arch.tlb_sets));
|
||||
DEFINE(KVM_SDR1, offsetof(struct kvm, arch.sdr1));
|
||||
DEFINE(KVM_HOST_LPID, offsetof(struct kvm, arch.host_lpid));
|
||||
DEFINE(KVM_HOST_LPCR, offsetof(struct kvm, arch.host_lpcr));
|
||||
DEFINE(KVM_HOST_SDR1, offsetof(struct kvm, arch.host_sdr1));
|
||||
DEFINE(KVM_NEED_FLUSH, offsetof(struct kvm, arch.need_tlb_flush.bits));
|
||||
DEFINE(KVM_ENABLED_HCALLS, offsetof(struct kvm, arch.enabled_hcalls));
|
||||
DEFINE(KVM_VRMA_SLB_V, offsetof(struct kvm, arch.vrma_slb_v));
|
||||
DEFINE(KVM_RADIX, offsetof(struct kvm, arch.radix));
|
||||
DEFINE(VCPU_DSISR, offsetof(struct kvm_vcpu, arch.shregs.dsisr));
|
||||
DEFINE(VCPU_DAR, offsetof(struct kvm_vcpu, arch.shregs.dar));
|
||||
DEFINE(VCPU_VPA, offsetof(struct kvm_vcpu, arch.vpa.pinned_addr));
|
||||
DEFINE(VCPU_VPA_DIRTY, offsetof(struct kvm_vcpu, arch.vpa.dirty));
|
||||
DEFINE(VCPU_HEIR, offsetof(struct kvm_vcpu, arch.emul_inst));
|
||||
DEFINE(VCPU_CPU, offsetof(struct kvm_vcpu, cpu));
|
||||
DEFINE(VCPU_THREAD_CPU, offsetof(struct kvm_vcpu, arch.thread_cpu));
|
||||
OFFSET(KVM_TLB_SETS, kvm, arch.tlb_sets);
|
||||
OFFSET(KVM_SDR1, kvm, arch.sdr1);
|
||||
OFFSET(KVM_HOST_LPID, kvm, arch.host_lpid);
|
||||
OFFSET(KVM_HOST_LPCR, kvm, arch.host_lpcr);
|
||||
OFFSET(KVM_HOST_SDR1, kvm, arch.host_sdr1);
|
||||
OFFSET(KVM_NEED_FLUSH, kvm, arch.need_tlb_flush.bits);
|
||||
OFFSET(KVM_ENABLED_HCALLS, kvm, arch.enabled_hcalls);
|
||||
OFFSET(KVM_VRMA_SLB_V, kvm, arch.vrma_slb_v);
|
||||
OFFSET(KVM_RADIX, kvm, arch.radix);
|
||||
OFFSET(VCPU_DSISR, kvm_vcpu, arch.shregs.dsisr);
|
||||
OFFSET(VCPU_DAR, kvm_vcpu, arch.shregs.dar);
|
||||
OFFSET(VCPU_VPA, kvm_vcpu, arch.vpa.pinned_addr);
|
||||
OFFSET(VCPU_VPA_DIRTY, kvm_vcpu, arch.vpa.dirty);
|
||||
OFFSET(VCPU_HEIR, kvm_vcpu, arch.emul_inst);
|
||||
OFFSET(VCPU_CPU, kvm_vcpu, cpu);
|
||||
OFFSET(VCPU_THREAD_CPU, kvm_vcpu, arch.thread_cpu);
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_BOOK3S
|
||||
DEFINE(VCPU_PURR, offsetof(struct kvm_vcpu, arch.purr));
|
||||
DEFINE(VCPU_SPURR, offsetof(struct kvm_vcpu, arch.spurr));
|
||||
DEFINE(VCPU_IC, offsetof(struct kvm_vcpu, arch.ic));
|
||||
DEFINE(VCPU_DSCR, offsetof(struct kvm_vcpu, arch.dscr));
|
||||
DEFINE(VCPU_AMR, offsetof(struct kvm_vcpu, arch.amr));
|
||||
DEFINE(VCPU_UAMOR, offsetof(struct kvm_vcpu, arch.uamor));
|
||||
DEFINE(VCPU_IAMR, offsetof(struct kvm_vcpu, arch.iamr));
|
||||
DEFINE(VCPU_CTRL, offsetof(struct kvm_vcpu, arch.ctrl));
|
||||
DEFINE(VCPU_DABR, offsetof(struct kvm_vcpu, arch.dabr));
|
||||
DEFINE(VCPU_DABRX, offsetof(struct kvm_vcpu, arch.dabrx));
|
||||
DEFINE(VCPU_DAWR, offsetof(struct kvm_vcpu, arch.dawr));
|
||||
DEFINE(VCPU_DAWRX, offsetof(struct kvm_vcpu, arch.dawrx));
|
||||
DEFINE(VCPU_CIABR, offsetof(struct kvm_vcpu, arch.ciabr));
|
||||
DEFINE(VCPU_HFLAGS, offsetof(struct kvm_vcpu, arch.hflags));
|
||||
DEFINE(VCPU_DEC, offsetof(struct kvm_vcpu, arch.dec));
|
||||
DEFINE(VCPU_DEC_EXPIRES, offsetof(struct kvm_vcpu, arch.dec_expires));
|
||||
DEFINE(VCPU_PENDING_EXC, offsetof(struct kvm_vcpu, arch.pending_exceptions));
|
||||
DEFINE(VCPU_CEDED, offsetof(struct kvm_vcpu, arch.ceded));
|
||||
DEFINE(VCPU_PRODDED, offsetof(struct kvm_vcpu, arch.prodded));
|
||||
DEFINE(VCPU_MMCR, offsetof(struct kvm_vcpu, arch.mmcr));
|
||||
DEFINE(VCPU_PMC, offsetof(struct kvm_vcpu, arch.pmc));
|
||||
DEFINE(VCPU_SPMC, offsetof(struct kvm_vcpu, arch.spmc));
|
||||
DEFINE(VCPU_SIAR, offsetof(struct kvm_vcpu, arch.siar));
|
||||
DEFINE(VCPU_SDAR, offsetof(struct kvm_vcpu, arch.sdar));
|
||||
DEFINE(VCPU_SIER, offsetof(struct kvm_vcpu, arch.sier));
|
||||
DEFINE(VCPU_SLB, offsetof(struct kvm_vcpu, arch.slb));
|
||||
DEFINE(VCPU_SLB_MAX, offsetof(struct kvm_vcpu, arch.slb_max));
|
||||
DEFINE(VCPU_SLB_NR, offsetof(struct kvm_vcpu, arch.slb_nr));
|
||||
DEFINE(VCPU_FAULT_DSISR, offsetof(struct kvm_vcpu, arch.fault_dsisr));
|
||||
DEFINE(VCPU_FAULT_DAR, offsetof(struct kvm_vcpu, arch.fault_dar));
|
||||
DEFINE(VCPU_FAULT_GPA, offsetof(struct kvm_vcpu, arch.fault_gpa));
|
||||
DEFINE(VCPU_INTR_MSR, offsetof(struct kvm_vcpu, arch.intr_msr));
|
||||
DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
|
||||
DEFINE(VCPU_TRAP, offsetof(struct kvm_vcpu, arch.trap));
|
||||
DEFINE(VCPU_CFAR, offsetof(struct kvm_vcpu, arch.cfar));
|
||||
DEFINE(VCPU_PPR, offsetof(struct kvm_vcpu, arch.ppr));
|
||||
DEFINE(VCPU_FSCR, offsetof(struct kvm_vcpu, arch.fscr));
|
||||
DEFINE(VCPU_PSPB, offsetof(struct kvm_vcpu, arch.pspb));
|
||||
DEFINE(VCPU_EBBHR, offsetof(struct kvm_vcpu, arch.ebbhr));
|
||||
DEFINE(VCPU_EBBRR, offsetof(struct kvm_vcpu, arch.ebbrr));
|
||||
DEFINE(VCPU_BESCR, offsetof(struct kvm_vcpu, arch.bescr));
|
||||
DEFINE(VCPU_CSIGR, offsetof(struct kvm_vcpu, arch.csigr));
|
||||
DEFINE(VCPU_TACR, offsetof(struct kvm_vcpu, arch.tacr));
|
||||
DEFINE(VCPU_TCSCR, offsetof(struct kvm_vcpu, arch.tcscr));
|
||||
DEFINE(VCPU_ACOP, offsetof(struct kvm_vcpu, arch.acop));
|
||||
DEFINE(VCPU_WORT, offsetof(struct kvm_vcpu, arch.wort));
|
||||
DEFINE(VCPU_TID, offsetof(struct kvm_vcpu, arch.tid));
|
||||
DEFINE(VCPU_PSSCR, offsetof(struct kvm_vcpu, arch.psscr));
|
||||
DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_map));
|
||||
DEFINE(VCORE_IN_GUEST, offsetof(struct kvmppc_vcore, in_guest));
|
||||
DEFINE(VCORE_NAPPING_THREADS, offsetof(struct kvmppc_vcore, napping_threads));
|
||||
DEFINE(VCORE_KVM, offsetof(struct kvmppc_vcore, kvm));
|
||||
DEFINE(VCORE_TB_OFFSET, offsetof(struct kvmppc_vcore, tb_offset));
|
||||
DEFINE(VCORE_LPCR, offsetof(struct kvmppc_vcore, lpcr));
|
||||
DEFINE(VCORE_PCR, offsetof(struct kvmppc_vcore, pcr));
|
||||
DEFINE(VCORE_DPDES, offsetof(struct kvmppc_vcore, dpdes));
|
||||
DEFINE(VCORE_VTB, offsetof(struct kvmppc_vcore, vtb));
|
||||
DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige));
|
||||
DEFINE(VCPU_SLB_V, offsetof(struct kvmppc_slb, origv));
|
||||
OFFSET(VCPU_PURR, kvm_vcpu, arch.purr);
|
||||
OFFSET(VCPU_SPURR, kvm_vcpu, arch.spurr);
|
||||
OFFSET(VCPU_IC, kvm_vcpu, arch.ic);
|
||||
OFFSET(VCPU_DSCR, kvm_vcpu, arch.dscr);
|
||||
OFFSET(VCPU_AMR, kvm_vcpu, arch.amr);
|
||||
OFFSET(VCPU_UAMOR, kvm_vcpu, arch.uamor);
|
||||
OFFSET(VCPU_IAMR, kvm_vcpu, arch.iamr);
|
||||
OFFSET(VCPU_CTRL, kvm_vcpu, arch.ctrl);
|
||||
OFFSET(VCPU_DABR, kvm_vcpu, arch.dabr);
|
||||
OFFSET(VCPU_DABRX, kvm_vcpu, arch.dabrx);
|
||||
OFFSET(VCPU_DAWR, kvm_vcpu, arch.dawr);
|
||||
OFFSET(VCPU_DAWRX, kvm_vcpu, arch.dawrx);
|
||||
OFFSET(VCPU_CIABR, kvm_vcpu, arch.ciabr);
|
||||
OFFSET(VCPU_HFLAGS, kvm_vcpu, arch.hflags);
|
||||
OFFSET(VCPU_DEC, kvm_vcpu, arch.dec);
|
||||
OFFSET(VCPU_DEC_EXPIRES, kvm_vcpu, arch.dec_expires);
|
||||
OFFSET(VCPU_PENDING_EXC, kvm_vcpu, arch.pending_exceptions);
|
||||
OFFSET(VCPU_CEDED, kvm_vcpu, arch.ceded);
|
||||
OFFSET(VCPU_PRODDED, kvm_vcpu, arch.prodded);
|
||||
OFFSET(VCPU_MMCR, kvm_vcpu, arch.mmcr);
|
||||
OFFSET(VCPU_PMC, kvm_vcpu, arch.pmc);
|
||||
OFFSET(VCPU_SPMC, kvm_vcpu, arch.spmc);
|
||||
OFFSET(VCPU_SIAR, kvm_vcpu, arch.siar);
|
||||
OFFSET(VCPU_SDAR, kvm_vcpu, arch.sdar);
|
||||
OFFSET(VCPU_SIER, kvm_vcpu, arch.sier);
|
||||
OFFSET(VCPU_SLB, kvm_vcpu, arch.slb);
|
||||
OFFSET(VCPU_SLB_MAX, kvm_vcpu, arch.slb_max);
|
||||
OFFSET(VCPU_SLB_NR, kvm_vcpu, arch.slb_nr);
|
||||
OFFSET(VCPU_FAULT_DSISR, kvm_vcpu, arch.fault_dsisr);
|
||||
OFFSET(VCPU_FAULT_DAR, kvm_vcpu, arch.fault_dar);
|
||||
OFFSET(VCPU_FAULT_GPA, kvm_vcpu, arch.fault_gpa);
|
||||
OFFSET(VCPU_INTR_MSR, kvm_vcpu, arch.intr_msr);
|
||||
OFFSET(VCPU_LAST_INST, kvm_vcpu, arch.last_inst);
|
||||
OFFSET(VCPU_TRAP, kvm_vcpu, arch.trap);
|
||||
OFFSET(VCPU_CFAR, kvm_vcpu, arch.cfar);
|
||||
OFFSET(VCPU_PPR, kvm_vcpu, arch.ppr);
|
||||
OFFSET(VCPU_FSCR, kvm_vcpu, arch.fscr);
|
||||
OFFSET(VCPU_PSPB, kvm_vcpu, arch.pspb);
|
||||
OFFSET(VCPU_EBBHR, kvm_vcpu, arch.ebbhr);
|
||||
OFFSET(VCPU_EBBRR, kvm_vcpu, arch.ebbrr);
|
||||
OFFSET(VCPU_BESCR, kvm_vcpu, arch.bescr);
|
||||
OFFSET(VCPU_CSIGR, kvm_vcpu, arch.csigr);
|
||||
OFFSET(VCPU_TACR, kvm_vcpu, arch.tacr);
|
||||
OFFSET(VCPU_TCSCR, kvm_vcpu, arch.tcscr);
|
||||
OFFSET(VCPU_ACOP, kvm_vcpu, arch.acop);
|
||||
OFFSET(VCPU_WORT, kvm_vcpu, arch.wort);
|
||||
OFFSET(VCPU_TID, kvm_vcpu, arch.tid);
|
||||
OFFSET(VCPU_PSSCR, kvm_vcpu, arch.psscr);
|
||||
OFFSET(VCORE_ENTRY_EXIT, kvmppc_vcore, entry_exit_map);
|
||||
OFFSET(VCORE_IN_GUEST, kvmppc_vcore, in_guest);
|
||||
OFFSET(VCORE_NAPPING_THREADS, kvmppc_vcore, napping_threads);
|
||||
OFFSET(VCORE_KVM, kvmppc_vcore, kvm);
|
||||
OFFSET(VCORE_TB_OFFSET, kvmppc_vcore, tb_offset);
|
||||
OFFSET(VCORE_LPCR, kvmppc_vcore, lpcr);
|
||||
OFFSET(VCORE_PCR, kvmppc_vcore, pcr);
|
||||
OFFSET(VCORE_DPDES, kvmppc_vcore, dpdes);
|
||||
OFFSET(VCORE_VTB, kvmppc_vcore, vtb);
|
||||
OFFSET(VCPU_SLB_E, kvmppc_slb, orige);
|
||||
OFFSET(VCPU_SLB_V, kvmppc_slb, origv);
|
||||
DEFINE(VCPU_SLB_SIZE, sizeof(struct kvmppc_slb));
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
DEFINE(VCPU_TFHAR, offsetof(struct kvm_vcpu, arch.tfhar));
|
||||
DEFINE(VCPU_TFIAR, offsetof(struct kvm_vcpu, arch.tfiar));
|
||||
DEFINE(VCPU_TEXASR, offsetof(struct kvm_vcpu, arch.texasr));
|
||||
DEFINE(VCPU_GPR_TM, offsetof(struct kvm_vcpu, arch.gpr_tm));
|
||||
DEFINE(VCPU_FPRS_TM, offsetof(struct kvm_vcpu, arch.fp_tm.fpr));
|
||||
DEFINE(VCPU_VRS_TM, offsetof(struct kvm_vcpu, arch.vr_tm.vr));
|
||||
DEFINE(VCPU_VRSAVE_TM, offsetof(struct kvm_vcpu, arch.vrsave_tm));
|
||||
DEFINE(VCPU_CR_TM, offsetof(struct kvm_vcpu, arch.cr_tm));
|
||||
DEFINE(VCPU_XER_TM, offsetof(struct kvm_vcpu, arch.xer_tm));
|
||||
DEFINE(VCPU_LR_TM, offsetof(struct kvm_vcpu, arch.lr_tm));
|
||||
DEFINE(VCPU_CTR_TM, offsetof(struct kvm_vcpu, arch.ctr_tm));
|
||||
DEFINE(VCPU_AMR_TM, offsetof(struct kvm_vcpu, arch.amr_tm));
|
||||
DEFINE(VCPU_PPR_TM, offsetof(struct kvm_vcpu, arch.ppr_tm));
|
||||
DEFINE(VCPU_DSCR_TM, offsetof(struct kvm_vcpu, arch.dscr_tm));
|
||||
DEFINE(VCPU_TAR_TM, offsetof(struct kvm_vcpu, arch.tar_tm));
|
||||
OFFSET(VCPU_TFHAR, kvm_vcpu, arch.tfhar);
|
||||
OFFSET(VCPU_TFIAR, kvm_vcpu, arch.tfiar);
|
||||
OFFSET(VCPU_TEXASR, kvm_vcpu, arch.texasr);
|
||||
OFFSET(VCPU_GPR_TM, kvm_vcpu, arch.gpr_tm);
|
||||
OFFSET(VCPU_FPRS_TM, kvm_vcpu, arch.fp_tm.fpr);
|
||||
OFFSET(VCPU_VRS_TM, kvm_vcpu, arch.vr_tm.vr);
|
||||
OFFSET(VCPU_VRSAVE_TM, kvm_vcpu, arch.vrsave_tm);
|
||||
OFFSET(VCPU_CR_TM, kvm_vcpu, arch.cr_tm);
|
||||
OFFSET(VCPU_XER_TM, kvm_vcpu, arch.xer_tm);
|
||||
OFFSET(VCPU_LR_TM, kvm_vcpu, arch.lr_tm);
|
||||
OFFSET(VCPU_CTR_TM, kvm_vcpu, arch.ctr_tm);
|
||||
OFFSET(VCPU_AMR_TM, kvm_vcpu, arch.amr_tm);
|
||||
OFFSET(VCPU_PPR_TM, kvm_vcpu, arch.ppr_tm);
|
||||
OFFSET(VCPU_DSCR_TM, kvm_vcpu, arch.dscr_tm);
|
||||
OFFSET(VCPU_TAR_TM, kvm_vcpu, arch.tar_tm);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
|
||||
DEFINE(PACA_SVCPU, offsetof(struct paca_struct, shadow_vcpu));
|
||||
OFFSET(PACA_SVCPU, paca_struct, shadow_vcpu);
|
||||
# define SVCPU_FIELD(x, f) DEFINE(x, offsetof(struct paca_struct, shadow_vcpu.f))
|
||||
#else
|
||||
# define SVCPU_FIELD(x, f)
|
||||
|
@ -668,11 +653,11 @@ int main(void)
|
|||
HSTATE_FIELD(HSTATE_DECEXP, dec_expires);
|
||||
HSTATE_FIELD(HSTATE_SPLIT_MODE, kvm_split_mode);
|
||||
DEFINE(IPI_PRIORITY, IPI_PRIORITY);
|
||||
DEFINE(KVM_SPLIT_RPR, offsetof(struct kvm_split_mode, rpr));
|
||||
DEFINE(KVM_SPLIT_PMMAR, offsetof(struct kvm_split_mode, pmmar));
|
||||
DEFINE(KVM_SPLIT_LDBAR, offsetof(struct kvm_split_mode, ldbar));
|
||||
DEFINE(KVM_SPLIT_DO_NAP, offsetof(struct kvm_split_mode, do_nap));
|
||||
DEFINE(KVM_SPLIT_NAPPED, offsetof(struct kvm_split_mode, napped));
|
||||
OFFSET(KVM_SPLIT_RPR, kvm_split_mode, rpr);
|
||||
OFFSET(KVM_SPLIT_PMMAR, kvm_split_mode, pmmar);
|
||||
OFFSET(KVM_SPLIT_LDBAR, kvm_split_mode, ldbar);
|
||||
OFFSET(KVM_SPLIT_DO_NAP, kvm_split_mode, do_nap);
|
||||
OFFSET(KVM_SPLIT_NAPPED, kvm_split_mode, napped);
|
||||
#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
|
@ -682,32 +667,27 @@ int main(void)
|
|||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
|
||||
#else /* CONFIG_PPC_BOOK3S */
|
||||
DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
|
||||
DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
|
||||
DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
|
||||
DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
|
||||
DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc));
|
||||
DEFINE(VCPU_SPRG9, offsetof(struct kvm_vcpu, arch.sprg9));
|
||||
DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
|
||||
DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear));
|
||||
DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr));
|
||||
DEFINE(VCPU_CRIT_SAVE, offsetof(struct kvm_vcpu, arch.crit_save));
|
||||
OFFSET(VCPU_CR, kvm_vcpu, arch.cr);
|
||||
OFFSET(VCPU_XER, kvm_vcpu, arch.xer);
|
||||
OFFSET(VCPU_LR, kvm_vcpu, arch.lr);
|
||||
OFFSET(VCPU_CTR, kvm_vcpu, arch.ctr);
|
||||
OFFSET(VCPU_PC, kvm_vcpu, arch.pc);
|
||||
OFFSET(VCPU_SPRG9, kvm_vcpu, arch.sprg9);
|
||||
OFFSET(VCPU_LAST_INST, kvm_vcpu, arch.last_inst);
|
||||
OFFSET(VCPU_FAULT_DEAR, kvm_vcpu, arch.fault_dear);
|
||||
OFFSET(VCPU_FAULT_ESR, kvm_vcpu, arch.fault_esr);
|
||||
OFFSET(VCPU_CRIT_SAVE, kvm_vcpu, arch.crit_save);
|
||||
#endif /* CONFIG_PPC_BOOK3S */
|
||||
#endif /* CONFIG_KVM */
|
||||
|
||||
#ifdef CONFIG_KVM_GUEST
|
||||
DEFINE(KVM_MAGIC_SCRATCH1, offsetof(struct kvm_vcpu_arch_shared,
|
||||
scratch1));
|
||||
DEFINE(KVM_MAGIC_SCRATCH2, offsetof(struct kvm_vcpu_arch_shared,
|
||||
scratch2));
|
||||
DEFINE(KVM_MAGIC_SCRATCH3, offsetof(struct kvm_vcpu_arch_shared,
|
||||
scratch3));
|
||||
DEFINE(KVM_MAGIC_INT, offsetof(struct kvm_vcpu_arch_shared,
|
||||
int_pending));
|
||||
DEFINE(KVM_MAGIC_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
|
||||
DEFINE(KVM_MAGIC_CRITICAL, offsetof(struct kvm_vcpu_arch_shared,
|
||||
critical));
|
||||
DEFINE(KVM_MAGIC_SR, offsetof(struct kvm_vcpu_arch_shared, sr));
|
||||
OFFSET(KVM_MAGIC_SCRATCH1, kvm_vcpu_arch_shared, scratch1);
|
||||
OFFSET(KVM_MAGIC_SCRATCH2, kvm_vcpu_arch_shared, scratch2);
|
||||
OFFSET(KVM_MAGIC_SCRATCH3, kvm_vcpu_arch_shared, scratch3);
|
||||
OFFSET(KVM_MAGIC_INT, kvm_vcpu_arch_shared, int_pending);
|
||||
OFFSET(KVM_MAGIC_MSR, kvm_vcpu_arch_shared, msr);
|
||||
OFFSET(KVM_MAGIC_CRITICAL, kvm_vcpu_arch_shared, critical);
|
||||
OFFSET(KVM_MAGIC_SR, kvm_vcpu_arch_shared, sr);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_44x
|
||||
|
@ -716,45 +696,37 @@ int main(void)
|
|||
#endif
|
||||
#ifdef CONFIG_PPC_FSL_BOOK3E
|
||||
DEFINE(TLBCAM_SIZE, sizeof(struct tlbcam));
|
||||
DEFINE(TLBCAM_MAS0, offsetof(struct tlbcam, MAS0));
|
||||
DEFINE(TLBCAM_MAS1, offsetof(struct tlbcam, MAS1));
|
||||
DEFINE(TLBCAM_MAS2, offsetof(struct tlbcam, MAS2));
|
||||
DEFINE(TLBCAM_MAS3, offsetof(struct tlbcam, MAS3));
|
||||
DEFINE(TLBCAM_MAS7, offsetof(struct tlbcam, MAS7));
|
||||
OFFSET(TLBCAM_MAS0, tlbcam, MAS0);
|
||||
OFFSET(TLBCAM_MAS1, tlbcam, MAS1);
|
||||
OFFSET(TLBCAM_MAS2, tlbcam, MAS2);
|
||||
OFFSET(TLBCAM_MAS3, tlbcam, MAS3);
|
||||
OFFSET(TLBCAM_MAS7, tlbcam, MAS7);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_KVM) && defined(CONFIG_SPE)
|
||||
DEFINE(VCPU_EVR, offsetof(struct kvm_vcpu, arch.evr[0]));
|
||||
DEFINE(VCPU_ACC, offsetof(struct kvm_vcpu, arch.acc));
|
||||
DEFINE(VCPU_SPEFSCR, offsetof(struct kvm_vcpu, arch.spefscr));
|
||||
DEFINE(VCPU_HOST_SPEFSCR, offsetof(struct kvm_vcpu, arch.host_spefscr));
|
||||
OFFSET(VCPU_EVR, kvm_vcpu, arch.evr[0]);
|
||||
OFFSET(VCPU_ACC, kvm_vcpu, arch.acc);
|
||||
OFFSET(VCPU_SPEFSCR, kvm_vcpu, arch.spefscr);
|
||||
OFFSET(VCPU_HOST_SPEFSCR, kvm_vcpu, arch.host_spefscr);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KVM_BOOKE_HV
|
||||
DEFINE(VCPU_HOST_MAS4, offsetof(struct kvm_vcpu, arch.host_mas4));
|
||||
DEFINE(VCPU_HOST_MAS6, offsetof(struct kvm_vcpu, arch.host_mas6));
|
||||
OFFSET(VCPU_HOST_MAS4, kvm_vcpu, arch.host_mas4);
|
||||
OFFSET(VCPU_HOST_MAS6, kvm_vcpu, arch.host_mas6);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KVM_EXIT_TIMING
|
||||
DEFINE(VCPU_TIMING_EXIT_TBU, offsetof(struct kvm_vcpu,
|
||||
arch.timing_exit.tv32.tbu));
|
||||
DEFINE(VCPU_TIMING_EXIT_TBL, offsetof(struct kvm_vcpu,
|
||||
arch.timing_exit.tv32.tbl));
|
||||
DEFINE(VCPU_TIMING_LAST_ENTER_TBU, offsetof(struct kvm_vcpu,
|
||||
arch.timing_last_enter.tv32.tbu));
|
||||
DEFINE(VCPU_TIMING_LAST_ENTER_TBL, offsetof(struct kvm_vcpu,
|
||||
arch.timing_last_enter.tv32.tbl));
|
||||
OFFSET(VCPU_TIMING_EXIT_TBU, kvm_vcpu, arch.timing_exit.tv32.tbu);
|
||||
OFFSET(VCPU_TIMING_EXIT_TBL, kvm_vcpu, arch.timing_exit.tv32.tbl);
|
||||
OFFSET(VCPU_TIMING_LAST_ENTER_TBU, kvm_vcpu, arch.timing_last_enter.tv32.tbu);
|
||||
OFFSET(VCPU_TIMING_LAST_ENTER_TBL, kvm_vcpu, arch.timing_last_enter.tv32.tbl);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_POWERNV
|
||||
DEFINE(PACA_CORE_IDLE_STATE_PTR,
|
||||
offsetof(struct paca_struct, core_idle_state_ptr));
|
||||
DEFINE(PACA_THREAD_IDLE_STATE,
|
||||
offsetof(struct paca_struct, thread_idle_state));
|
||||
DEFINE(PACA_THREAD_MASK,
|
||||
offsetof(struct paca_struct, thread_mask));
|
||||
DEFINE(PACA_SUBCORE_SIBLING_MASK,
|
||||
offsetof(struct paca_struct, subcore_sibling_mask));
|
||||
OFFSET(PACA_CORE_IDLE_STATE_PTR, paca_struct, core_idle_state_ptr);
|
||||
OFFSET(PACA_THREAD_IDLE_STATE, paca_struct, thread_idle_state);
|
||||
OFFSET(PACA_THREAD_MASK, paca_struct, thread_mask);
|
||||
OFFSET(PACA_SUBCORE_SIBLING_MASK, paca_struct, subcore_sibling_mask);
|
||||
#endif
|
||||
|
||||
DEFINE(PPC_DBELL_SERVER, PPC_DBELL_SERVER);
|
||||
|
|
|
@ -101,6 +101,8 @@ _GLOBAL(__setup_cpu_power9)
|
|||
mfspr r3,SPRN_LPCR
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE)
|
||||
or r3, r3, r4
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_UPRT | LPCR_HR)
|
||||
andc r3, r3, r4
|
||||
bl __init_LPCR
|
||||
bl __init_HFSCR
|
||||
bl __init_tlb_power9
|
||||
|
@ -122,6 +124,8 @@ _GLOBAL(__restore_cpu_power9)
|
|||
mfspr r3,SPRN_LPCR
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE)
|
||||
or r3, r3, r4
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_UPRT | LPCR_HR)
|
||||
andc r3, r3, r4
|
||||
bl __init_LPCR
|
||||
bl __init_HFSCR
|
||||
bl __init_tlb_power9
|
||||
|
|
|
@ -386,6 +386,23 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
|||
.machine_check_early = __machine_check_early_realmode_p8,
|
||||
.platform = "power8",
|
||||
},
|
||||
{ /* 3.00-compliant processor, i.e. Power9 "architected" mode */
|
||||
.pvr_mask = 0xffffffff,
|
||||
.pvr_value = 0x0f000005,
|
||||
.cpu_name = "POWER9 (architected)",
|
||||
.cpu_features = CPU_FTRS_POWER9,
|
||||
.cpu_user_features = COMMON_USER_POWER9,
|
||||
.cpu_user_features2 = COMMON_USER2_POWER9,
|
||||
.mmu_features = MMU_FTRS_POWER9,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.oprofile_type = PPC_OPROFILE_INVALID,
|
||||
.oprofile_cpu_type = "ppc64/ibm-compat-v1",
|
||||
.cpu_setup = __setup_cpu_power9,
|
||||
.cpu_restore = __restore_cpu_power9,
|
||||
.flush_tlb = __flush_tlb_power9,
|
||||
.platform = "power9",
|
||||
},
|
||||
{ /* Power7 */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x003f0000,
|
||||
|
|
|
@ -205,6 +205,9 @@ transfer_to_handler_cont:
|
|||
mflr r9
|
||||
lwz r11,0(r9) /* virtual address of handler */
|
||||
lwz r9,4(r9) /* where to go when done */
|
||||
#ifdef CONFIG_PPC_8xx_PERF_EVENT
|
||||
mtspr SPRN_NRI, r0
|
||||
#endif
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
lis r12,reenable_mmu@h
|
||||
ori r12,r12,reenable_mmu@l
|
||||
|
@ -292,7 +295,9 @@ stack_ovf:
|
|||
lis r9,StackOverflow@ha
|
||||
addi r9,r9,StackOverflow@l
|
||||
LOAD_MSR_KERNEL(r10,MSR_KERNEL)
|
||||
FIX_SRR1(r10,r12)
|
||||
#ifdef CONFIG_PPC_8xx_PERF_EVENT
|
||||
mtspr SPRN_NRI, r0
|
||||
#endif
|
||||
mtspr SPRN_SRR0,r9
|
||||
mtspr SPRN_SRR1,r10
|
||||
SYNC
|
||||
|
@ -417,9 +422,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
|
|||
mtlr r4
|
||||
mtcr r5
|
||||
lwz r7,_NIP(r1)
|
||||
FIX_SRR1(r8, r0)
|
||||
lwz r2,GPR2(r1)
|
||||
lwz r1,GPR1(r1)
|
||||
#ifdef CONFIG_PPC_8xx_PERF_EVENT
|
||||
mtspr SPRN_NRI, r0
|
||||
#endif
|
||||
mtspr SPRN_SRR0,r7
|
||||
mtspr SPRN_SRR1,r8
|
||||
SYNC
|
||||
|
@ -699,6 +706,9 @@ fast_exception_return:
|
|||
lwz r10,_LINK(r11)
|
||||
mtlr r10
|
||||
REST_GPR(10, r11)
|
||||
#ifdef CONFIG_PPC_8xx_PERF_EVENT
|
||||
mtspr SPRN_NRI, r0
|
||||
#endif
|
||||
mtspr SPRN_SRR1,r9
|
||||
mtspr SPRN_SRR0,r12
|
||||
REST_GPR(9, r11)
|
||||
|
@ -947,7 +957,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
|
|||
.globl exc_exit_restart
|
||||
exc_exit_restart:
|
||||
lwz r12,_NIP(r1)
|
||||
FIX_SRR1(r9,r10)
|
||||
#ifdef CONFIG_PPC_8xx_PERF_EVENT
|
||||
mtspr SPRN_NRI, r0
|
||||
#endif
|
||||
mtspr SPRN_SRR0,r12
|
||||
mtspr SPRN_SRR1,r9
|
||||
REST_4GPRS(9, r1)
|
||||
|
@ -1290,7 +1302,6 @@ _GLOBAL(enter_rtas)
|
|||
1: tophys(r9,r1)
|
||||
lwz r8,INT_FRAME_SIZE+4(r9) /* get return address */
|
||||
lwz r9,8(r9) /* original msr value */
|
||||
FIX_SRR1(r9,r0)
|
||||
addi r1,r1,INT_FRAME_SIZE
|
||||
li r0,0
|
||||
mtspr SPRN_SPRG_RTAS,r0
|
||||
|
|
|
@ -869,7 +869,6 @@ __secondary_start:
|
|||
|
||||
/* enable MMU and jump to start_secondary */
|
||||
li r4,MSR_KERNEL
|
||||
FIX_SRR1(r4,r5)
|
||||
lis r3,start_secondary@h
|
||||
ori r3,r3,start_secondary@l
|
||||
mtspr SPRN_SRR0,r3
|
||||
|
@ -977,7 +976,6 @@ start_here:
|
|||
ori r4,r4,2f@l
|
||||
tophys(r4,r4)
|
||||
li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
|
||||
FIX_SRR1(r3,r5)
|
||||
mtspr SPRN_SRR0,r4
|
||||
mtspr SPRN_SRR1,r3
|
||||
SYNC
|
||||
|
@ -1001,7 +999,6 @@ start_here:
|
|||
|
||||
/* Now turn on the MMU for real! */
|
||||
li r4,MSR_KERNEL
|
||||
FIX_SRR1(r4,r5)
|
||||
lis r3,start_kernel@h
|
||||
ori r3,r3,start_kernel@l
|
||||
mtspr SPRN_SRR0,r3
|
||||
|
|
|
@ -329,6 +329,12 @@ InstructionTLBMiss:
|
|||
mtspr SPRN_SPRG_SCRATCH2, r3
|
||||
#endif
|
||||
EXCEPTION_PROLOG_0
|
||||
#ifdef CONFIG_PPC_8xx_PERF_EVENT
|
||||
lis r10, (itlb_miss_counter - PAGE_OFFSET)@ha
|
||||
lwz r11, (itlb_miss_counter - PAGE_OFFSET)@l(r10)
|
||||
addi r11, r11, 1
|
||||
stw r11, (itlb_miss_counter - PAGE_OFFSET)@l(r10)
|
||||
#endif
|
||||
|
||||
/* If we are faulting a kernel address, we have to use the
|
||||
* kernel page tables.
|
||||
|
@ -429,6 +435,12 @@ InstructionTLBMiss:
|
|||
DataStoreTLBMiss:
|
||||
mtspr SPRN_SPRG_SCRATCH2, r3
|
||||
EXCEPTION_PROLOG_0
|
||||
#ifdef CONFIG_PPC_8xx_PERF_EVENT
|
||||
lis r10, (dtlb_miss_counter - PAGE_OFFSET)@ha
|
||||
lwz r11, (dtlb_miss_counter - PAGE_OFFSET)@l(r10)
|
||||
addi r11, r11, 1
|
||||
stw r11, (dtlb_miss_counter - PAGE_OFFSET)@l(r10)
|
||||
#endif
|
||||
mfcr r3
|
||||
|
||||
/* If we are faulting a kernel address, we have to use the
|
||||
|
@ -561,6 +573,7 @@ InstructionTLBError:
|
|||
andis. r10,r5,0x4000
|
||||
beq+ 1f
|
||||
tlbie r4
|
||||
itlbie:
|
||||
/* 0x400 is InstructionAccess exception, needed by bad_page_fault() */
|
||||
1: EXC_XFER_LITE(0x400, handle_page_fault)
|
||||
|
||||
|
@ -585,6 +598,7 @@ DARFixed:/* Return from dcbx instruction bug workaround */
|
|||
andis. r10,r5,0x4000
|
||||
beq+ 1f
|
||||
tlbie r4
|
||||
dtlbie:
|
||||
1: li r10,RPN_PATTERN
|
||||
mtspr SPRN_DAR,r10 /* Tag DAR, to be used in DTLB Error */
|
||||
/* 0x300 is DataAccess exception, needed by bad_page_fault() */
|
||||
|
@ -602,8 +616,43 @@ DARFixed:/* Return from dcbx instruction bug workaround */
|
|||
* support of breakpoints and such. Someday I will get around to
|
||||
* using them.
|
||||
*/
|
||||
EXCEPTION(0x1c00, Trap_1c, unknown_exception, EXC_XFER_EE)
|
||||
. = 0x1c00
|
||||
DataBreakpoint:
|
||||
EXCEPTION_PROLOG_0
|
||||
mfcr r10
|
||||
mfspr r11, SPRN_SRR0
|
||||
cmplwi cr0, r11, (dtlbie - PAGE_OFFSET)@l
|
||||
cmplwi cr7, r11, (itlbie - PAGE_OFFSET)@l
|
||||
beq- cr0, 11f
|
||||
beq- cr7, 11f
|
||||
EXCEPTION_PROLOG_1
|
||||
EXCEPTION_PROLOG_2
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
mfspr r4,SPRN_BAR
|
||||
stw r4,_DAR(r11)
|
||||
mfspr r5,SPRN_DSISR
|
||||
EXC_XFER_EE(0x1c00, do_break)
|
||||
11:
|
||||
mtcr r10
|
||||
EXCEPTION_EPILOG_0
|
||||
rfi
|
||||
|
||||
#ifdef CONFIG_PPC_8xx_PERF_EVENT
|
||||
. = 0x1d00
|
||||
InstructionBreakpoint:
|
||||
EXCEPTION_PROLOG_0
|
||||
lis r10, (instruction_counter - PAGE_OFFSET)@ha
|
||||
lwz r11, (instruction_counter - PAGE_OFFSET)@l(r10)
|
||||
addi r11, r11, -1
|
||||
stw r11, (instruction_counter - PAGE_OFFSET)@l(r10)
|
||||
lis r10, 0xffff
|
||||
ori r10, r10, 0x01
|
||||
mtspr SPRN_COUNTA, r10
|
||||
EXCEPTION_EPILOG_0
|
||||
rfi
|
||||
#else
|
||||
EXCEPTION(0x1d00, Trap_1d, unknown_exception, EXC_XFER_EE)
|
||||
#endif
|
||||
EXCEPTION(0x1e00, Trap_1e, unknown_exception, EXC_XFER_EE)
|
||||
EXCEPTION(0x1f00, Trap_1f, unknown_exception, EXC_XFER_EE)
|
||||
|
||||
|
@ -977,6 +1026,14 @@ initial_mmu:
|
|||
lis r8, IDC_ENABLE@h
|
||||
mtspr SPRN_DC_CST, r8
|
||||
#endif
|
||||
/* Disable debug mode entry on breakpoints */
|
||||
mfspr r8, SPRN_DER
|
||||
#ifdef CONFIG_PPC_8xx_PERF_EVENT
|
||||
rlwinm r8, r8, 0, ~0xc
|
||||
#else
|
||||
rlwinm r8, r8, 0, ~0x8
|
||||
#endif
|
||||
mtspr SPRN_DER, r8
|
||||
blr
|
||||
|
||||
|
||||
|
@ -1010,3 +1067,16 @@ cpu6_errata_word:
|
|||
.space 16
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_8xx_PERF_EVENT
|
||||
.globl itlb_miss_counter
|
||||
itlb_miss_counter:
|
||||
.space 4
|
||||
|
||||
.globl dtlb_miss_counter
|
||||
dtlb_miss_counter:
|
||||
.space 4
|
||||
|
||||
.globl instruction_counter
|
||||
instruction_counter:
|
||||
.space 4
|
||||
#endif
|
||||
|
|
|
@ -211,9 +211,11 @@ int hw_breakpoint_handler(struct die_args *args)
|
|||
int rc = NOTIFY_STOP;
|
||||
struct perf_event *bp;
|
||||
struct pt_regs *regs = args->regs;
|
||||
#ifndef CONFIG_PPC_8xx
|
||||
int stepped = 1;
|
||||
struct arch_hw_breakpoint *info;
|
||||
unsigned int instr;
|
||||
#endif
|
||||
struct arch_hw_breakpoint *info;
|
||||
unsigned long dar = regs->dar;
|
||||
|
||||
/* Disable breakpoints during exception handling */
|
||||
|
@ -257,6 +259,7 @@ int hw_breakpoint_handler(struct die_args *args)
|
|||
(dar - bp->attr.bp_addr < bp->attr.bp_len)))
|
||||
info->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ;
|
||||
|
||||
#ifndef CONFIG_PPC_8xx
|
||||
/* Do not emulate user-space instructions, instead single-step them */
|
||||
if (user_mode(regs)) {
|
||||
current->thread.last_hit_ubp = bp;
|
||||
|
@ -280,6 +283,7 @@ int hw_breakpoint_handler(struct die_args *args)
|
|||
perf_event_disable_inatomic(bp);
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* As a policy, the callback is invoked in a 'trigger-after-execute'
|
||||
* fashion
|
||||
|
|
|
@ -65,6 +65,13 @@ optprobe_template_entry:
|
|||
mfdsisr r5
|
||||
std r5,_DSISR(r1)
|
||||
|
||||
/*
|
||||
* We may get here from a module, so load the kernel TOC in r2.
|
||||
* The original TOC gets restored when pt_regs is restored
|
||||
* further below.
|
||||
*/
|
||||
ld r2,PACATOC(r13)
|
||||
|
||||
.global optprobe_template_op_address
|
||||
optprobe_template_op_address:
|
||||
/*
|
||||
|
|
|
@ -1560,16 +1560,10 @@ static void pcibios_setup_phb_resources(struct pci_controller *hose,
|
|||
/* Hookup PHB Memory resources */
|
||||
for (i = 0; i < 3; ++i) {
|
||||
res = &hose->mem_resources[i];
|
||||
if (!res->flags) {
|
||||
if (i == 0)
|
||||
printk(KERN_ERR "PCI: Memory resource 0 not set for "
|
||||
"host bridge %s (domain %d)\n",
|
||||
hose->dn->full_name, hose->global_number);
|
||||
if (!res->flags)
|
||||
continue;
|
||||
}
|
||||
|
||||
offset = hose->mem_offset[i];
|
||||
|
||||
|
||||
pr_debug("PCI: PHB MEM resource %d = %pR off 0x%08llx\n", i,
|
||||
res, (unsigned long long)offset);
|
||||
|
||||
|
|
|
@ -730,6 +730,28 @@ static inline int __set_dabr(unsigned long dabr, unsigned long dabrx)
|
|||
mtspr(SPRN_DABRX, dabrx);
|
||||
return 0;
|
||||
}
|
||||
#elif defined(CONFIG_PPC_8xx)
|
||||
static inline int __set_dabr(unsigned long dabr, unsigned long dabrx)
|
||||
{
|
||||
unsigned long addr = dabr & ~HW_BRK_TYPE_DABR;
|
||||
unsigned long lctrl1 = 0x90000000; /* compare type: equal on E & F */
|
||||
unsigned long lctrl2 = 0x8e000002; /* watchpoint 1 on cmp E | F */
|
||||
|
||||
if ((dabr & HW_BRK_TYPE_RDWR) == HW_BRK_TYPE_READ)
|
||||
lctrl1 |= 0xa0000;
|
||||
else if ((dabr & HW_BRK_TYPE_RDWR) == HW_BRK_TYPE_WRITE)
|
||||
lctrl1 |= 0xf0000;
|
||||
else if ((dabr & HW_BRK_TYPE_RDWR) == 0)
|
||||
lctrl2 = 0;
|
||||
|
||||
mtspr(SPRN_LCTRL2, 0);
|
||||
mtspr(SPRN_CMPE, addr);
|
||||
mtspr(SPRN_CMPF, addr + 4);
|
||||
mtspr(SPRN_LCTRL1, lctrl1);
|
||||
mtspr(SPRN_LCTRL2, lctrl2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int __set_dabr(unsigned long dabr, unsigned long dabrx)
|
||||
{
|
||||
|
|
|
@ -839,7 +839,7 @@ struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = {
|
|||
0,
|
||||
#endif
|
||||
.associativity = OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
|
||||
.bin_opts = OV5_FEAT(OV5_RESIZE_HPT),
|
||||
.bin_opts = OV5_FEAT(OV5_RESIZE_HPT) | OV5_FEAT(OV5_HP_EVT),
|
||||
.micro_checkpoint = 0,
|
||||
.reserved0 = 0,
|
||||
.max_cpus = cpu_to_be32(NR_CPUS), /* number of cores supported */
|
||||
|
|
|
@ -113,14 +113,12 @@ void __init setup_tlb_core_data(void)
|
|||
* If we have threads, we need either tlbsrx.
|
||||
* or e6500 tablewalk mode, or else TLB handlers
|
||||
* will be racy and could produce duplicate entries.
|
||||
* Should we panic instead?
|
||||
*/
|
||||
if (smt_enabled_at_boot >= 2 &&
|
||||
!mmu_has_feature(MMU_FTR_USE_TLBRSRV) &&
|
||||
book3e_htw_mode != PPC_HTW_E6500) {
|
||||
/* Should we panic instead? */
|
||||
WARN_ONCE("%s: unsupported MMU configuration -- expect problems\n",
|
||||
__func__);
|
||||
}
|
||||
WARN_ONCE(smt_enabled_at_boot >= 2 &&
|
||||
!mmu_has_feature(MMU_FTR_USE_TLBRSRV) &&
|
||||
book3e_htw_mode != PPC_HTW_E6500,
|
||||
"%s: unsupported MMU configuration\n", __func__);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -709,7 +709,7 @@ unsigned long long running_clock(void)
|
|||
* time and on a host which doesn't do any virtualisation TB *should* equal
|
||||
* VTB so it makes no difference anyway.
|
||||
*/
|
||||
return local_clock() - cputime_to_nsecs(kcpustat_this_cpu->cpustat[CPUTIME_STEAL]);
|
||||
return local_clock() - kcpustat_this_cpu->cpustat[CPUTIME_STEAL];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -193,9 +193,7 @@ void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
|
|||
*/
|
||||
VM_WARN_ON(pte_present(*ptep) && !pte_protnone(*ptep));
|
||||
|
||||
/*
|
||||
* Add the pte bit when tryint set a pte
|
||||
*/
|
||||
/* Add the pte bit when trying to set a pte */
|
||||
pte = __pte(pte_val(pte) | _PAGE_PTE);
|
||||
|
||||
/* Note: mm->context.id might not yet have been assigned as
|
||||
|
|
|
@ -71,9 +71,9 @@ slb_miss_kernel_load_linear:
|
|||
|
||||
|
||||
BEGIN_FTR_SECTION
|
||||
b slb_finish_load
|
||||
b .Lslb_finish_load
|
||||
END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
|
||||
b slb_finish_load_1T
|
||||
b .Lslb_finish_load_1T
|
||||
|
||||
1:
|
||||
#ifdef CONFIG_SPARSEMEM_VMEMMAP
|
||||
|
@ -109,9 +109,9 @@ slb_miss_kernel_load_io:
|
|||
addi r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@l
|
||||
|
||||
BEGIN_FTR_SECTION
|
||||
b slb_finish_load
|
||||
b .Lslb_finish_load
|
||||
END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
|
||||
b slb_finish_load_1T
|
||||
b .Lslb_finish_load_1T
|
||||
|
||||
0: /*
|
||||
* For userspace addresses, make sure this is region 0.
|
||||
|
@ -174,9 +174,9 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
|
|||
ld r9,PACACONTEXTID(r13)
|
||||
BEGIN_FTR_SECTION
|
||||
cmpldi r10,0x1000
|
||||
bge slb_finish_load_1T
|
||||
bge .Lslb_finish_load_1T
|
||||
END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
|
||||
b slb_finish_load
|
||||
b .Lslb_finish_load
|
||||
|
||||
8: /* invalid EA - return an error indication */
|
||||
crset 4*cr0+eq /* indicate failure */
|
||||
|
@ -187,7 +187,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
|
|||
*
|
||||
* r3 = EA, r9 = context, r10 = ESID, r11 = flags, clobbers r9, cr7 = <> PAGE_OFFSET
|
||||
*/
|
||||
slb_finish_load:
|
||||
.Lslb_finish_load:
|
||||
rldimi r10,r9,ESID_BITS,0
|
||||
ASM_VSID_SCRAMBLE(r10,r9,256M)
|
||||
/*
|
||||
|
@ -256,7 +256,7 @@ slb_compare_rr_to_size:
|
|||
*
|
||||
* r3 = EA, r9 = context, r10 = ESID(256MB), r11 = flags, clobbers r9
|
||||
*/
|
||||
slb_finish_load_1T:
|
||||
.Lslb_finish_load_1T:
|
||||
srdi r10,r10,(SID_SHIFT_1T - SID_SHIFT) /* get 1T ESID */
|
||||
rldimi r10,r9,ESID_BITS_1T,0
|
||||
ASM_VSID_SCRAMBLE(r10,r9,1T)
|
||||
|
@ -272,3 +272,11 @@ slb_finish_load_1T:
|
|||
clrrdi r3,r3,SID_SHIFT_1T /* clear out non-ESID bits */
|
||||
b 7b
|
||||
|
||||
|
||||
_ASM_NOKPROBE_SYMBOL(slb_allocate_realmode)
|
||||
_ASM_NOKPROBE_SYMBOL(slb_miss_kernel_load_linear)
|
||||
_ASM_NOKPROBE_SYMBOL(slb_miss_kernel_load_io)
|
||||
_ASM_NOKPROBE_SYMBOL(slb_compare_rr_to_size)
|
||||
#ifdef CONFIG_SPARSEMEM_VMEMMAP
|
||||
_ASM_NOKPROBE_SYMBOL(slb_miss_kernel_load_vmemmap)
|
||||
#endif
|
||||
|
|
173
arch/powerpc/perf/8xx-pmu.c
Normal file
173
arch/powerpc/perf/8xx-pmu.c
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Performance event support - PPC 8xx
|
||||
*
|
||||
* Copyright 2016 Christophe Leroy, CS Systemes d'Information
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <asm/pmc.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
#define PERF_8xx_ID_CPU_CYCLES 1
|
||||
#define PERF_8xx_ID_HW_INSTRUCTIONS 2
|
||||
#define PERF_8xx_ID_ITLB_LOAD_MISS 3
|
||||
#define PERF_8xx_ID_DTLB_LOAD_MISS 4
|
||||
|
||||
#define C(x) PERF_COUNT_HW_CACHE_##x
|
||||
#define DTLB_LOAD_MISS (C(DTLB) | (C(OP_READ) << 8) | (C(RESULT_MISS) << 16))
|
||||
#define ITLB_LOAD_MISS (C(ITLB) | (C(OP_READ) << 8) | (C(RESULT_MISS) << 16))
|
||||
|
||||
extern unsigned long itlb_miss_counter, dtlb_miss_counter;
|
||||
extern atomic_t instruction_counter;
|
||||
|
||||
static atomic_t insn_ctr_ref;
|
||||
|
||||
static s64 get_insn_ctr(void)
|
||||
{
|
||||
int ctr;
|
||||
unsigned long counta;
|
||||
|
||||
do {
|
||||
ctr = atomic_read(&instruction_counter);
|
||||
counta = mfspr(SPRN_COUNTA);
|
||||
} while (ctr != atomic_read(&instruction_counter));
|
||||
|
||||
return ((s64)ctr << 16) | (counta >> 16);
|
||||
}
|
||||
|
||||
static int event_type(struct perf_event *event)
|
||||
{
|
||||
switch (event->attr.type) {
|
||||
case PERF_TYPE_HARDWARE:
|
||||
if (event->attr.config == PERF_COUNT_HW_CPU_CYCLES)
|
||||
return PERF_8xx_ID_CPU_CYCLES;
|
||||
if (event->attr.config == PERF_COUNT_HW_INSTRUCTIONS)
|
||||
return PERF_8xx_ID_HW_INSTRUCTIONS;
|
||||
break;
|
||||
case PERF_TYPE_HW_CACHE:
|
||||
if (event->attr.config == ITLB_LOAD_MISS)
|
||||
return PERF_8xx_ID_ITLB_LOAD_MISS;
|
||||
if (event->attr.config == DTLB_LOAD_MISS)
|
||||
return PERF_8xx_ID_DTLB_LOAD_MISS;
|
||||
break;
|
||||
case PERF_TYPE_RAW:
|
||||
break;
|
||||
default:
|
||||
return -ENOENT;
|
||||
}
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int mpc8xx_pmu_event_init(struct perf_event *event)
|
||||
{
|
||||
int type = event_type(event);
|
||||
|
||||
if (type < 0)
|
||||
return type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpc8xx_pmu_add(struct perf_event *event, int flags)
|
||||
{
|
||||
int type = event_type(event);
|
||||
s64 val = 0;
|
||||
|
||||
if (type < 0)
|
||||
return type;
|
||||
|
||||
switch (type) {
|
||||
case PERF_8xx_ID_CPU_CYCLES:
|
||||
val = get_tb();
|
||||
break;
|
||||
case PERF_8xx_ID_HW_INSTRUCTIONS:
|
||||
if (atomic_inc_return(&insn_ctr_ref) == 1)
|
||||
mtspr(SPRN_ICTRL, 0xc0080007);
|
||||
val = get_insn_ctr();
|
||||
break;
|
||||
case PERF_8xx_ID_ITLB_LOAD_MISS:
|
||||
val = itlb_miss_counter;
|
||||
break;
|
||||
case PERF_8xx_ID_DTLB_LOAD_MISS:
|
||||
val = dtlb_miss_counter;
|
||||
break;
|
||||
}
|
||||
local64_set(&event->hw.prev_count, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mpc8xx_pmu_read(struct perf_event *event)
|
||||
{
|
||||
int type = event_type(event);
|
||||
s64 prev, val = 0, delta = 0;
|
||||
|
||||
if (type < 0)
|
||||
return;
|
||||
|
||||
do {
|
||||
prev = local64_read(&event->hw.prev_count);
|
||||
switch (type) {
|
||||
case PERF_8xx_ID_CPU_CYCLES:
|
||||
val = get_tb();
|
||||
delta = 16 * (val - prev);
|
||||
break;
|
||||
case PERF_8xx_ID_HW_INSTRUCTIONS:
|
||||
val = get_insn_ctr();
|
||||
delta = prev - val;
|
||||
if (delta < 0)
|
||||
delta += 0x1000000000000LL;
|
||||
break;
|
||||
case PERF_8xx_ID_ITLB_LOAD_MISS:
|
||||
val = itlb_miss_counter;
|
||||
delta = (s64)((s32)val - (s32)prev);
|
||||
break;
|
||||
case PERF_8xx_ID_DTLB_LOAD_MISS:
|
||||
val = dtlb_miss_counter;
|
||||
delta = (s64)((s32)val - (s32)prev);
|
||||
break;
|
||||
}
|
||||
} while (local64_cmpxchg(&event->hw.prev_count, prev, val) != prev);
|
||||
|
||||
local64_add(delta, &event->count);
|
||||
}
|
||||
|
||||
static void mpc8xx_pmu_del(struct perf_event *event, int flags)
|
||||
{
|
||||
mpc8xx_pmu_read(event);
|
||||
if (event_type(event) != PERF_8xx_ID_HW_INSTRUCTIONS)
|
||||
return;
|
||||
|
||||
/* If it was the last user, stop counting to avoid useles overhead */
|
||||
if (atomic_dec_return(&insn_ctr_ref) == 0)
|
||||
mtspr(SPRN_ICTRL, 7);
|
||||
}
|
||||
|
||||
static struct pmu mpc8xx_pmu = {
|
||||
.event_init = mpc8xx_pmu_event_init,
|
||||
.add = mpc8xx_pmu_add,
|
||||
.del = mpc8xx_pmu_del,
|
||||
.read = mpc8xx_pmu_read,
|
||||
.capabilities = PERF_PMU_CAP_NO_INTERRUPT |
|
||||
PERF_PMU_CAP_NO_NMI,
|
||||
};
|
||||
|
||||
static int init_mpc8xx_pmu(void)
|
||||
{
|
||||
mtspr(SPRN_ICTRL, 7);
|
||||
mtspr(SPRN_CMPA, 0);
|
||||
mtspr(SPRN_COUNTA, 0xffff);
|
||||
|
||||
return perf_pmu_register(&mpc8xx_pmu, "cpu", PERF_TYPE_RAW);
|
||||
}
|
||||
|
||||
early_initcall(init_mpc8xx_pmu);
|
|
@ -13,5 +13,7 @@ obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o e6500-pmu.o
|
|||
|
||||
obj-$(CONFIG_HV_PERF_CTRS) += hv-24x7.o hv-gpci.o hv-common.o
|
||||
|
||||
obj-$(CONFIG_PPC_8xx_PERF_EVENT) += 8xx-pmu.o
|
||||
|
||||
obj-$(CONFIG_PPC64) += $(obj64-y)
|
||||
obj-$(CONFIG_PPC32) += $(obj32-y)
|
||||
|
|
|
@ -57,6 +57,7 @@ struct cpu_hw_events {
|
|||
void *bhrb_context;
|
||||
struct perf_branch_stack bhrb_stack;
|
||||
struct perf_branch_entry bhrb_entries[BHRB_MAX_ENTRIES];
|
||||
u64 ic_init;
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
|
||||
|
@ -127,6 +128,10 @@ static inline void power_pmu_bhrb_disable(struct perf_event *event) {}
|
|||
static void power_pmu_sched_task(struct perf_event_context *ctx, bool sched_in) {}
|
||||
static inline void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) {}
|
||||
static void pmao_restore_workaround(bool ebb) { }
|
||||
static bool use_ic(u64 event)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_PPC32 */
|
||||
|
||||
static bool regs_use_siar(struct pt_regs *regs)
|
||||
|
@ -243,7 +248,7 @@ static inline u32 perf_get_misc_flags(struct pt_regs *regs)
|
|||
*/
|
||||
if (ppmu->flags & PPMU_NO_SIPR) {
|
||||
unsigned long siar = mfspr(SPRN_SIAR);
|
||||
if (siar >= PAGE_OFFSET)
|
||||
if (is_kernel_addr(siar))
|
||||
return PERF_RECORD_MISC_KERNEL;
|
||||
return PERF_RECORD_MISC_USER;
|
||||
}
|
||||
|
@ -688,6 +693,15 @@ static void pmao_restore_workaround(bool ebb)
|
|||
mtspr(SPRN_PMC5, pmcs[4]);
|
||||
mtspr(SPRN_PMC6, pmcs[5]);
|
||||
}
|
||||
|
||||
static bool use_ic(u64 event)
|
||||
{
|
||||
if (cpu_has_feature(CPU_FTR_POWER9_DD1) &&
|
||||
(event == 0x200f2 || event == 0x300f2))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
static void perf_event_interrupt(struct pt_regs *regs);
|
||||
|
@ -1007,6 +1021,7 @@ static u64 check_and_compute_delta(u64 prev, u64 val)
|
|||
static void power_pmu_read(struct perf_event *event)
|
||||
{
|
||||
s64 val, delta, prev;
|
||||
struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events);
|
||||
|
||||
if (event->hw.state & PERF_HES_STOPPED)
|
||||
return;
|
||||
|
@ -1016,6 +1031,13 @@ static void power_pmu_read(struct perf_event *event)
|
|||
|
||||
if (is_ebb_event(event)) {
|
||||
val = read_pmc(event->hw.idx);
|
||||
if (use_ic(event->attr.config)) {
|
||||
val = mfspr(SPRN_IC);
|
||||
if (val > cpuhw->ic_init)
|
||||
val = val - cpuhw->ic_init;
|
||||
else
|
||||
val = val + (0 - cpuhw->ic_init);
|
||||
}
|
||||
local64_set(&event->hw.prev_count, val);
|
||||
return;
|
||||
}
|
||||
|
@ -1029,6 +1051,13 @@ static void power_pmu_read(struct perf_event *event)
|
|||
prev = local64_read(&event->hw.prev_count);
|
||||
barrier();
|
||||
val = read_pmc(event->hw.idx);
|
||||
if (use_ic(event->attr.config)) {
|
||||
val = mfspr(SPRN_IC);
|
||||
if (val > cpuhw->ic_init)
|
||||
val = val - cpuhw->ic_init;
|
||||
else
|
||||
val = val + (0 - cpuhw->ic_init);
|
||||
}
|
||||
delta = check_and_compute_delta(prev, val);
|
||||
if (!delta)
|
||||
return;
|
||||
|
@ -1466,6 +1495,13 @@ static int power_pmu_add(struct perf_event *event, int ef_flags)
|
|||
event->attr.branch_sample_type);
|
||||
}
|
||||
|
||||
/*
|
||||
* Workaround for POWER9 DD1 to use the Instruction Counter
|
||||
* register value for instruction counting
|
||||
*/
|
||||
if (use_ic(event->attr.config))
|
||||
cpuhw->ic_init = mfspr(SPRN_IC);
|
||||
|
||||
perf_pmu_enable(event->pmu);
|
||||
local_irq_restore(flags);
|
||||
return ret;
|
||||
|
|
|
@ -97,6 +97,28 @@ static unsigned long combine_shift(unsigned long pmc)
|
|||
return MMCR1_COMBINE_SHIFT(pmc);
|
||||
}
|
||||
|
||||
static inline bool event_is_threshold(u64 event)
|
||||
{
|
||||
return (event >> EVENT_THR_SEL_SHIFT) & EVENT_THR_SEL_MASK;
|
||||
}
|
||||
|
||||
static bool is_thresh_cmp_valid(u64 event)
|
||||
{
|
||||
unsigned int cmp, exp;
|
||||
|
||||
/*
|
||||
* Check the mantissa upper two bits are not zero, unless the
|
||||
* exponent is also zero. See the THRESH_CMP_MANTISSA doc.
|
||||
*/
|
||||
cmp = (event >> EVENT_THR_CMP_SHIFT) & EVENT_THR_CMP_MASK;
|
||||
exp = cmp >> 7;
|
||||
|
||||
if (exp && (cmp & 0x60) == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp)
|
||||
{
|
||||
unsigned int unit, pmc, cache, ebb;
|
||||
|
@ -163,28 +185,26 @@ int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp)
|
|||
value |= CNST_SAMPLE_VAL(event >> EVENT_SAMPLE_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Special case for PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC,
|
||||
* the threshold control bits are used for the match value.
|
||||
*/
|
||||
if (event_is_fab_match(event)) {
|
||||
mask |= CNST_FAB_MATCH_MASK;
|
||||
value |= CNST_FAB_MATCH_VAL(event >> EVENT_THR_CTL_SHIFT);
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_300)) {
|
||||
if (event_is_threshold(event) && is_thresh_cmp_valid(event)) {
|
||||
mask |= CNST_THRESH_MASK;
|
||||
value |= CNST_THRESH_VAL(event >> EVENT_THRESH_SHIFT);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Check the mantissa upper two bits are not zero, unless the
|
||||
* exponent is also zero. See the THRESH_CMP_MANTISSA doc.
|
||||
* Special case for PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC,
|
||||
* the threshold control bits are used for the match value.
|
||||
*/
|
||||
unsigned int cmp, exp;
|
||||
if (event_is_fab_match(event)) {
|
||||
mask |= CNST_FAB_MATCH_MASK;
|
||||
value |= CNST_FAB_MATCH_VAL(event >> EVENT_THR_CTL_SHIFT);
|
||||
} else {
|
||||
if (!is_thresh_cmp_valid(event))
|
||||
return -1;
|
||||
|
||||
cmp = (event >> EVENT_THR_CMP_SHIFT) & EVENT_THR_CMP_MASK;
|
||||
exp = cmp >> 7;
|
||||
|
||||
if (exp && (cmp & 0x60) == 0)
|
||||
return -1;
|
||||
|
||||
mask |= CNST_THRESH_MASK;
|
||||
value |= CNST_THRESH_VAL(event >> EVENT_THRESH_SHIFT);
|
||||
mask |= CNST_THRESH_MASK;
|
||||
value |= CNST_THRESH_VAL(event >> EVENT_THRESH_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pmc && ebb)
|
||||
|
@ -279,7 +299,7 @@ int isa207_compute_mmcr(u64 event[], int n_ev,
|
|||
* PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC,
|
||||
* the threshold bits are used for the match value.
|
||||
*/
|
||||
if (event_is_fab_match(event[i])) {
|
||||
if (!cpu_has_feature(CPU_FTR_ARCH_300) && event_is_fab_match(event[i])) {
|
||||
mmcr1 |= ((event[i] >> EVENT_THR_CTL_SHIFT) &
|
||||
EVENT_THR_CTL_MASK) << MMCR1_FAB_SHIFT;
|
||||
} else {
|
||||
|
@ -338,3 +358,39 @@ void isa207_disable_pmc(unsigned int pmc, unsigned long mmcr[])
|
|||
if (pmc <= 3)
|
||||
mmcr[1] &= ~(0xffUL << MMCR1_PMCSEL_SHIFT(pmc + 1));
|
||||
}
|
||||
|
||||
static int find_alternative(u64 event, const unsigned int ev_alt[][MAX_ALT], int size)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < size; ++i) {
|
||||
if (event < ev_alt[i][0])
|
||||
break;
|
||||
|
||||
for (j = 0; j < MAX_ALT && ev_alt[i][j]; ++j)
|
||||
if (event == ev_alt[i][j])
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int isa207_get_alternatives(u64 event, u64 alt[],
|
||||
const unsigned int ev_alt[][MAX_ALT], int size)
|
||||
{
|
||||
int i, j, num_alt = 0;
|
||||
u64 alt_event;
|
||||
|
||||
alt[num_alt++] = event;
|
||||
i = find_alternative(event, ev_alt, size);
|
||||
if (i >= 0) {
|
||||
/* Filter out the original event, it's already in alt[0] */
|
||||
for (j = 0; j < MAX_ALT; ++j) {
|
||||
alt_event = ev_alt[i][j];
|
||||
if (alt_event && alt_event != event)
|
||||
alt[num_alt++] = alt_event;
|
||||
}
|
||||
}
|
||||
|
||||
return num_alt;
|
||||
}
|
||||
|
|
|
@ -222,6 +222,10 @@
|
|||
CNST_PMC_VAL(1) | CNST_PMC_VAL(2) | CNST_PMC_VAL(3) | \
|
||||
CNST_PMC_VAL(4) | CNST_PMC_VAL(5) | CNST_PMC_VAL(6) | CNST_NC_VAL
|
||||
|
||||
/*
|
||||
* Lets restrict use of PMC5 for instruction counting.
|
||||
*/
|
||||
#define P9_DD1_TEST_ADDER (ISA207_TEST_ADDER | CNST_PMC_VAL(5))
|
||||
|
||||
/* Bits in MMCR1 for PowerISA v2.07 */
|
||||
#define MMCR1_UNIT_SHIFT(pmc) (60 - (4 * ((pmc) - 1)))
|
||||
|
@ -260,5 +264,8 @@ int isa207_compute_mmcr(u64 event[], int n_ev,
|
|||
unsigned int hwc[], unsigned long mmcr[],
|
||||
struct perf_event *pevents[]);
|
||||
void isa207_disable_pmc(unsigned int pmc, unsigned long mmcr[]);
|
||||
int isa207_get_alternatives(u64 event, u64 alt[],
|
||||
const unsigned int ev_alt[][MAX_ALT], int size);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -48,43 +48,12 @@ static const unsigned int event_alternatives[][MAX_ALT] = {
|
|||
{ PM_RUN_INST_CMPL_ALT, PM_RUN_INST_CMPL },
|
||||
};
|
||||
|
||||
/*
|
||||
* Scan the alternatives table for a match and return the
|
||||
* index into the alternatives table if found, else -1.
|
||||
*/
|
||||
static int find_alternative(u64 event)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(event_alternatives); ++i) {
|
||||
if (event < event_alternatives[i][0])
|
||||
break;
|
||||
|
||||
for (j = 0; j < MAX_ALT && event_alternatives[i][j]; ++j)
|
||||
if (event == event_alternatives[i][j])
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int power8_get_alternatives(u64 event, unsigned int flags, u64 alt[])
|
||||
{
|
||||
int i, j, num_alt = 0;
|
||||
u64 alt_event;
|
||||
|
||||
alt[num_alt++] = event;
|
||||
|
||||
i = find_alternative(event);
|
||||
if (i >= 0) {
|
||||
/* Filter out the original event, it's already in alt[0] */
|
||||
for (j = 0; j < MAX_ALT; ++j) {
|
||||
alt_event = event_alternatives[i][j];
|
||||
if (alt_event && alt_event != event)
|
||||
alt[num_alt++] = alt_event;
|
||||
}
|
||||
}
|
||||
|
||||
num_alt = isa207_get_alternatives(event, alt, event_alternatives,
|
||||
(int)ARRAY_SIZE(event_alternatives));
|
||||
if (flags & PPMU_ONLY_COUNT_RUN) {
|
||||
/*
|
||||
* We're only counting in RUN state, so PM_CYC is equivalent to
|
||||
|
|
|
@ -53,3 +53,6 @@ EVENT(PM_ITLB_MISS, 0x400fc)
|
|||
EVENT(PM_RUN_INST_CMPL, 0x500fa)
|
||||
/* Run_cycles */
|
||||
EVENT(PM_RUN_CYC, 0x600f4)
|
||||
/* Instruction Dispatched */
|
||||
EVENT(PM_INST_DISP, 0x200f2)
|
||||
EVENT(PM_INST_DISP_ALT, 0x300f2)
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
|
||||
* | | [ ] [ ] [ thresh_cmp ] [ thresh_ctl ]
|
||||
* | | | | |
|
||||
* | | *- IFM (Linux) | thresh start/stop OR FAB match -*
|
||||
* | | *- IFM (Linux) | thresh start/stop -*
|
||||
* | *- BHRB (Linux) *sm
|
||||
* *- EBB (Linux)
|
||||
*
|
||||
|
@ -50,11 +50,9 @@
|
|||
* MMCR1[31] = pmc4combine[1]
|
||||
*
|
||||
* if pmc == 3 and unit == 0 and pmcxsel[0:6] == 0b0101011
|
||||
* # PM_MRK_FAB_RSP_MATCH
|
||||
* MMCR1[20:27] = thresh_ctl (FAB_CRESP_MATCH / FAB_TYPE_MATCH)
|
||||
* MMCR1[20:27] = thresh_ctl
|
||||
* else if pmc == 4 and unit == 0xf and pmcxsel[0:6] == 0b0101001
|
||||
* # PM_MRK_FAB_RSP_MATCH_CYC
|
||||
* MMCR1[20:27] = thresh_ctl (FAB_CRESP_MATCH / FAB_TYPE_MATCH)
|
||||
* MMCR1[20:27] = thresh_ctl
|
||||
* else
|
||||
* MMCRA[48:55] = thresh_ctl (THRESH START/END)
|
||||
*
|
||||
|
@ -106,6 +104,21 @@ enum {
|
|||
/* PowerISA v2.07 format attribute structure*/
|
||||
extern struct attribute_group isa207_pmu_format_group;
|
||||
|
||||
/* Table of alternatives, sorted by column 0 */
|
||||
static const unsigned int power9_event_alternatives[][MAX_ALT] = {
|
||||
{ PM_INST_DISP, PM_INST_DISP_ALT },
|
||||
};
|
||||
|
||||
static int power9_get_alternatives(u64 event, unsigned int flags, u64 alt[])
|
||||
{
|
||||
int num_alt = 0;
|
||||
|
||||
num_alt = isa207_get_alternatives(event, alt, power9_event_alternatives,
|
||||
(int)ARRAY_SIZE(power9_event_alternatives));
|
||||
|
||||
return num_alt;
|
||||
}
|
||||
|
||||
GENERIC_EVENT_ATTR(cpu-cycles, PM_CYC);
|
||||
GENERIC_EVENT_ATTR(stalled-cycles-frontend, PM_ICT_NOSLOT_CYC);
|
||||
GENERIC_EVENT_ATTR(stalled-cycles-backend, PM_CMPLU_STALL);
|
||||
|
@ -213,6 +226,17 @@ static const struct attribute_group *power9_pmu_attr_groups[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static int power9_generic_events_dd1[] = {
|
||||
[PERF_COUNT_HW_CPU_CYCLES] = PM_CYC,
|
||||
[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = PM_ICT_NOSLOT_CYC,
|
||||
[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = PM_CMPLU_STALL,
|
||||
[PERF_COUNT_HW_INSTRUCTIONS] = PM_INST_DISP,
|
||||
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = PM_BRU_CMPL,
|
||||
[PERF_COUNT_HW_BRANCH_MISSES] = PM_BR_MPRED_CMPL,
|
||||
[PERF_COUNT_HW_CACHE_REFERENCES] = PM_LD_REF_L1,
|
||||
[PERF_COUNT_HW_CACHE_MISSES] = PM_LD_MISS_L1_FIN,
|
||||
};
|
||||
|
||||
static int power9_generic_events[] = {
|
||||
[PERF_COUNT_HW_CPU_CYCLES] = PM_CYC,
|
||||
[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = PM_ICT_NOSLOT_CYC,
|
||||
|
@ -383,10 +407,11 @@ static struct power_pmu power9_isa207_pmu = {
|
|||
.config_bhrb = power9_config_bhrb,
|
||||
.bhrb_filter_map = power9_bhrb_filter_map,
|
||||
.get_constraint = isa207_get_constraint,
|
||||
.get_alternatives = power9_get_alternatives,
|
||||
.disable_pmc = isa207_disable_pmc,
|
||||
.flags = PPMU_NO_SIAR | PPMU_ARCH_207S,
|
||||
.n_generic = ARRAY_SIZE(power9_generic_events),
|
||||
.generic_events = power9_generic_events,
|
||||
.n_generic = ARRAY_SIZE(power9_generic_events_dd1),
|
||||
.generic_events = power9_generic_events_dd1,
|
||||
.cache_events = &power9_cache_events,
|
||||
.attr_groups = power9_isa207_pmu_attr_groups,
|
||||
.bhrb_nr = 32,
|
||||
|
@ -396,11 +421,12 @@ static struct power_pmu power9_pmu = {
|
|||
.name = "POWER9",
|
||||
.n_counter = MAX_PMU_COUNTERS,
|
||||
.add_fields = ISA207_ADD_FIELDS,
|
||||
.test_adder = ISA207_TEST_ADDER,
|
||||
.test_adder = P9_DD1_TEST_ADDER,
|
||||
.compute_mmcr = isa207_compute_mmcr,
|
||||
.config_bhrb = power9_config_bhrb,
|
||||
.bhrb_filter_map = power9_bhrb_filter_map,
|
||||
.get_constraint = isa207_get_constraint,
|
||||
.get_alternatives = power9_get_alternatives,
|
||||
.disable_pmc = isa207_disable_pmc,
|
||||
.flags = PPMU_HAS_SIER | PPMU_ARCH_207S,
|
||||
.n_generic = ARRAY_SIZE(power9_generic_events),
|
||||
|
@ -420,6 +446,11 @@ static int __init init_power9_pmu(void)
|
|||
return -ENODEV;
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_POWER9_DD1)) {
|
||||
/*
|
||||
* Since PM_INST_CMPL may not provide right counts in all
|
||||
* sampling scenarios in power9 DD1, instead use PM_INST_DISP.
|
||||
*/
|
||||
EVENT_VAR(PM_INST_CMPL, _g).id = PM_INST_DISP;
|
||||
rc = register_power_pmu(&power9_isa207_pmu);
|
||||
} else {
|
||||
rc = register_power_pmu(&power9_pmu);
|
||||
|
|
|
@ -22,6 +22,7 @@ obj-$(CONFIG_P1022_RDK) += p1022_rdk.o
|
|||
obj-$(CONFIG_P1023_RDB) += p1023_rdb.o
|
||||
obj-$(CONFIG_TWR_P102x) += twr_p102x.o
|
||||
obj-$(CONFIG_CORENET_GENERIC) += corenet_generic.o
|
||||
obj-$(CONFIG_FB_FSL_DIU) += t1042rdb_diu.o
|
||||
obj-$(CONFIG_STX_GP3) += stx_gp3.o
|
||||
obj-$(CONFIG_TQM85xx) += tqm85xx.o
|
||||
obj-$(CONFIG_SBC8548) += sbc8548.o
|
||||
|
|
|
@ -157,6 +157,7 @@ static const char * const boards[] __initconst = {
|
|||
"fsl,T1040RDB",
|
||||
"fsl,T1042RDB",
|
||||
"fsl,T1042RDB_PI",
|
||||
"keymile,kmcent2",
|
||||
"keymile,kmcoge4",
|
||||
"varisys,CYRUS",
|
||||
NULL
|
||||
|
|
152
arch/powerpc/platforms/85xx/t1042rdb_diu.c
Normal file
152
arch/powerpc/platforms/85xx/t1042rdb_diu.c
Normal file
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* T1042 platform DIU operation
|
||||
*
|
||||
* Copyright 2014 Freescale Semiconductor Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include <sysdev/fsl_soc.h>
|
||||
|
||||
/*DIU Pixel ClockCR offset in scfg*/
|
||||
#define CCSR_SCFG_PIXCLKCR 0x28
|
||||
|
||||
/* DIU Pixel Clock bits of the PIXCLKCR */
|
||||
#define PIXCLKCR_PXCKEN 0x80000000
|
||||
#define PIXCLKCR_PXCKINV 0x40000000
|
||||
#define PIXCLKCR_PXCKDLY 0x0000FF00
|
||||
#define PIXCLKCR_PXCLK_MASK 0x00FF0000
|
||||
|
||||
/* Some CPLD register definitions */
|
||||
#define CPLD_DIUCSR 0x16
|
||||
#define CPLD_DIUCSR_DVIEN 0x80
|
||||
#define CPLD_DIUCSR_BACKLIGHT 0x0f
|
||||
|
||||
struct device_node *cpld_node;
|
||||
|
||||
/**
|
||||
* t1042rdb_set_monitor_port: switch the output to a different monitor port
|
||||
*/
|
||||
static void t1042rdb_set_monitor_port(enum fsl_diu_monitor_port port)
|
||||
{
|
||||
static void __iomem *cpld_base;
|
||||
|
||||
cpld_base = of_iomap(cpld_node, 0);
|
||||
if (!cpld_base) {
|
||||
pr_err("%s: Could not map cpld registers\n", __func__);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch (port) {
|
||||
case FSL_DIU_PORT_DVI:
|
||||
/* Enable the DVI(HDMI) port, disable the DFP and
|
||||
* the backlight
|
||||
*/
|
||||
clrbits8(cpld_base + CPLD_DIUCSR, CPLD_DIUCSR_DVIEN);
|
||||
break;
|
||||
case FSL_DIU_PORT_LVDS:
|
||||
/*
|
||||
* LVDS also needs backlight enabled, otherwise the display
|
||||
* will be blank.
|
||||
*/
|
||||
/* Enable the DFP port, disable the DVI*/
|
||||
setbits8(cpld_base + CPLD_DIUCSR, 0x01 << 8);
|
||||
setbits8(cpld_base + CPLD_DIUCSR, 0x01 << 4);
|
||||
setbits8(cpld_base + CPLD_DIUCSR, CPLD_DIUCSR_BACKLIGHT);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Unsupported monitor port %i\n", __func__, port);
|
||||
}
|
||||
|
||||
iounmap(cpld_base);
|
||||
exit:
|
||||
of_node_put(cpld_node);
|
||||
}
|
||||
|
||||
/**
|
||||
* t1042rdb_set_pixel_clock: program the DIU's clock
|
||||
* @pixclock: pixel clock in ps (pico seconds)
|
||||
*/
|
||||
static void t1042rdb_set_pixel_clock(unsigned int pixclock)
|
||||
{
|
||||
struct device_node *scfg_np;
|
||||
void __iomem *scfg;
|
||||
unsigned long freq;
|
||||
u64 temp;
|
||||
u32 pxclk;
|
||||
|
||||
scfg_np = of_find_compatible_node(NULL, NULL, "fsl,t1040-scfg");
|
||||
if (!scfg_np) {
|
||||
pr_err("%s: Missing scfg node. Can not display video.\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
scfg = of_iomap(scfg_np, 0);
|
||||
of_node_put(scfg_np);
|
||||
if (!scfg) {
|
||||
pr_err("%s: Could not map device. Can not display video.\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Convert pixclock into frequency */
|
||||
temp = 1000000000000ULL;
|
||||
do_div(temp, pixclock);
|
||||
freq = temp;
|
||||
|
||||
/*
|
||||
* 'pxclk' is the ratio of the platform clock to the pixel clock.
|
||||
* This number is programmed into the PIXCLKCR register, and the valid
|
||||
* range of values is 2-255.
|
||||
*/
|
||||
pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq);
|
||||
pxclk = clamp_t(u32, pxclk, 2, 255);
|
||||
|
||||
/* Disable the pixel clock, and set it to non-inverted and no delay */
|
||||
clrbits32(scfg + CCSR_SCFG_PIXCLKCR,
|
||||
PIXCLKCR_PXCKEN | PIXCLKCR_PXCKDLY | PIXCLKCR_PXCLK_MASK);
|
||||
|
||||
/* Enable the clock and set the pxclk */
|
||||
setbits32(scfg + CCSR_SCFG_PIXCLKCR, PIXCLKCR_PXCKEN | (pxclk << 16));
|
||||
|
||||
iounmap(scfg);
|
||||
}
|
||||
|
||||
/**
|
||||
* t1042rdb_valid_monitor_port: set the monitor port for sysfs
|
||||
*/
|
||||
static enum fsl_diu_monitor_port
|
||||
t1042rdb_valid_monitor_port(enum fsl_diu_monitor_port port)
|
||||
{
|
||||
switch (port) {
|
||||
case FSL_DIU_PORT_DVI:
|
||||
case FSL_DIU_PORT_LVDS:
|
||||
return port;
|
||||
default:
|
||||
return FSL_DIU_PORT_DVI; /* Dual-link LVDS is not supported */
|
||||
}
|
||||
}
|
||||
|
||||
static int __init t1042rdb_diu_init(void)
|
||||
{
|
||||
cpld_node = of_find_compatible_node(NULL, NULL, "fsl,t1042rdb-cpld");
|
||||
if (!cpld_node)
|
||||
return 0;
|
||||
|
||||
diu_ops.set_monitor_port = t1042rdb_set_monitor_port;
|
||||
diu_ops.set_pixel_clock = t1042rdb_set_pixel_clock;
|
||||
diu_ops.valid_monitor_port = t1042rdb_valid_monitor_port;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
early_initcall(t1042rdb_diu_init);
|
|
@ -172,6 +172,13 @@ config PPC_FPU
|
|||
bool
|
||||
default y if PPC64
|
||||
|
||||
config PPC_8xx_PERF_EVENT
|
||||
bool "PPC 8xx perf events"
|
||||
depends on PPC_8xx && PERF_EVENTS
|
||||
help
|
||||
This is Performance Events support for PPC 8xx. The 8xx doesn't
|
||||
have a PMU but some events are emulated using 8xx features.
|
||||
|
||||
config FSL_EMB_PERFMON
|
||||
bool "Freescale Embedded Perfmon"
|
||||
depends on E500 || PPC_83xx
|
||||
|
|
|
@ -683,23 +683,13 @@ size_t spu_ibox_read(struct spu_context *ctx, u32 *data)
|
|||
return ctx->ops->ibox_read(ctx, data);
|
||||
}
|
||||
|
||||
static int spufs_ibox_fasync(int fd, struct file *file, int on)
|
||||
{
|
||||
struct spu_context *ctx = file->private_data;
|
||||
|
||||
return fasync_helper(fd, file, on, &ctx->ibox_fasync);
|
||||
}
|
||||
|
||||
/* interrupt-level ibox callback function. */
|
||||
void spufs_ibox_callback(struct spu *spu)
|
||||
{
|
||||
struct spu_context *ctx = spu->ctx;
|
||||
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
wake_up_all(&ctx->ibox_wq);
|
||||
kill_fasync(&ctx->ibox_fasync, SIGIO, POLLIN);
|
||||
if (ctx)
|
||||
wake_up_all(&ctx->ibox_wq);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -794,7 +784,6 @@ static const struct file_operations spufs_ibox_fops = {
|
|||
.open = spufs_pipe_open,
|
||||
.read = spufs_ibox_read,
|
||||
.poll = spufs_ibox_poll,
|
||||
.fasync = spufs_ibox_fasync,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
|
@ -832,26 +821,13 @@ size_t spu_wbox_write(struct spu_context *ctx, u32 data)
|
|||
return ctx->ops->wbox_write(ctx, data);
|
||||
}
|
||||
|
||||
static int spufs_wbox_fasync(int fd, struct file *file, int on)
|
||||
{
|
||||
struct spu_context *ctx = file->private_data;
|
||||
int ret;
|
||||
|
||||
ret = fasync_helper(fd, file, on, &ctx->wbox_fasync);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* interrupt-level wbox callback function. */
|
||||
void spufs_wbox_callback(struct spu *spu)
|
||||
{
|
||||
struct spu_context *ctx = spu->ctx;
|
||||
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
wake_up_all(&ctx->wbox_wq);
|
||||
kill_fasync(&ctx->wbox_fasync, SIGIO, POLLOUT);
|
||||
if (ctx)
|
||||
wake_up_all(&ctx->wbox_wq);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -944,7 +920,6 @@ static const struct file_operations spufs_wbox_fops = {
|
|||
.open = spufs_pipe_open,
|
||||
.write = spufs_wbox_write,
|
||||
.poll = spufs_wbox_poll,
|
||||
.fasync = spufs_wbox_fasync,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
|
@ -1520,28 +1495,8 @@ void spufs_mfc_callback(struct spu *spu)
|
|||
{
|
||||
struct spu_context *ctx = spu->ctx;
|
||||
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
wake_up_all(&ctx->mfc_wq);
|
||||
|
||||
pr_debug("%s %s\n", __func__, spu->name);
|
||||
if (ctx->mfc_fasync) {
|
||||
u32 free_elements, tagstatus;
|
||||
unsigned int mask;
|
||||
|
||||
/* no need for spu_acquire in interrupt context */
|
||||
free_elements = ctx->ops->get_mfc_free_elements(ctx);
|
||||
tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
|
||||
|
||||
mask = 0;
|
||||
if (free_elements & 0xffff)
|
||||
mask |= POLLOUT;
|
||||
if (tagstatus & ctx->tagwait)
|
||||
mask |= POLLIN;
|
||||
|
||||
kill_fasync(&ctx->mfc_fasync, SIGIO, mask);
|
||||
}
|
||||
if (ctx)
|
||||
wake_up_all(&ctx->mfc_wq);
|
||||
}
|
||||
|
||||
static int spufs_read_mfc_tagstatus(struct spu_context *ctx, u32 *status)
|
||||
|
@ -1803,13 +1758,6 @@ static int spufs_mfc_fsync(struct file *file, loff_t start, loff_t end, int data
|
|||
return err;
|
||||
}
|
||||
|
||||
static int spufs_mfc_fasync(int fd, struct file *file, int on)
|
||||
{
|
||||
struct spu_context *ctx = file->private_data;
|
||||
|
||||
return fasync_helper(fd, file, on, &ctx->mfc_fasync);
|
||||
}
|
||||
|
||||
static const struct file_operations spufs_mfc_fops = {
|
||||
.open = spufs_mfc_open,
|
||||
.release = spufs_mfc_release,
|
||||
|
@ -1818,7 +1766,6 @@ static const struct file_operations spufs_mfc_fops = {
|
|||
.poll = spufs_mfc_poll,
|
||||
.flush = spufs_mfc_flush,
|
||||
.fsync = spufs_mfc_fsync,
|
||||
.fasync = spufs_mfc_fasync,
|
||||
.mmap = spufs_mfc_mmap,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
|
|
@ -102,9 +102,6 @@ struct spu_context {
|
|||
wait_queue_head_t stop_wq;
|
||||
wait_queue_head_t mfc_wq;
|
||||
wait_queue_head_t run_wq;
|
||||
struct fasync_struct *ibox_fasync;
|
||||
struct fasync_struct *wbox_fasync;
|
||||
struct fasync_struct *mfc_fasync;
|
||||
u32 tagwait;
|
||||
struct spu_context_ops *ops;
|
||||
struct work_struct reap_work;
|
||||
|
|
|
@ -5,7 +5,8 @@ config PPC_POWERNV
|
|||
select PPC_XICS
|
||||
select PPC_ICP_NATIVE
|
||||
select PPC_P7_NAP
|
||||
select PPC_PCI_CHOICE if EMBEDDED
|
||||
select PCI
|
||||
select PCI_MSI
|
||||
select EPAPR_BOOT
|
||||
select PPC_INDIRECT_PIO
|
||||
select PPC_UDBG_16550
|
||||
|
|
|
@ -1468,14 +1468,12 @@ void pnv_pci_sriov_disable(struct pci_dev *pdev)
|
|||
struct pnv_phb *phb;
|
||||
struct pnv_ioda_pe *pe;
|
||||
struct pci_dn *pdn;
|
||||
struct pci_sriov *iov;
|
||||
u16 num_vfs, i;
|
||||
|
||||
bus = pdev->bus;
|
||||
hose = pci_bus_to_host(bus);
|
||||
phb = hose->private_data;
|
||||
pdn = pci_get_pdn(pdev);
|
||||
iov = pdev->sriov;
|
||||
num_vfs = pdn->num_vfs;
|
||||
|
||||
/* Release VF PEs */
|
||||
|
|
|
@ -354,11 +354,17 @@ static int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog)
|
|||
switch (hp_elog->id_type) {
|
||||
case PSERIES_HP_ELOG_ID_DRC_COUNT:
|
||||
hp_elog->_drc_u.drc_count =
|
||||
be32_to_cpu(hp_elog->_drc_u.drc_count);
|
||||
be32_to_cpu(hp_elog->_drc_u.drc_count);
|
||||
break;
|
||||
case PSERIES_HP_ELOG_ID_DRC_INDEX:
|
||||
hp_elog->_drc_u.drc_index =
|
||||
be32_to_cpu(hp_elog->_drc_u.drc_index);
|
||||
be32_to_cpu(hp_elog->_drc_u.drc_index);
|
||||
break;
|
||||
case PSERIES_HP_ELOG_ID_DRC_IC:
|
||||
hp_elog->_drc_u.ic.count =
|
||||
be32_to_cpu(hp_elog->_drc_u.ic.count);
|
||||
hp_elog->_drc_u.ic.index =
|
||||
be32_to_cpu(hp_elog->_drc_u.ic.index);
|
||||
}
|
||||
|
||||
switch (hp_elog->resource) {
|
||||
|
@ -467,7 +473,33 @@ static int dlpar_parse_id_type(char **cmd, struct pseries_hp_errorlog *hp_elog)
|
|||
if (!arg)
|
||||
return -EINVAL;
|
||||
|
||||
if (sysfs_streq(arg, "index")) {
|
||||
if (sysfs_streq(arg, "indexed-count")) {
|
||||
hp_elog->id_type = PSERIES_HP_ELOG_ID_DRC_IC;
|
||||
arg = strsep(cmd, " ");
|
||||
if (!arg) {
|
||||
pr_err("No DRC count specified.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (kstrtou32(arg, 0, &count)) {
|
||||
pr_err("Invalid DRC count specified.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
arg = strsep(cmd, " ");
|
||||
if (!arg) {
|
||||
pr_err("No DRC Index specified.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (kstrtou32(arg, 0, &index)) {
|
||||
pr_err("Invalid DRC Index specified.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hp_elog->_drc_u.ic.count = cpu_to_be32(count);
|
||||
hp_elog->_drc_u.ic.index = cpu_to_be32(index);
|
||||
} else if (sysfs_streq(arg, "index")) {
|
||||
hp_elog->id_type = PSERIES_HP_ELOG_ID_DRC_INDEX;
|
||||
arg = strsep(cmd, " ");
|
||||
if (!arg) {
|
||||
|
|
|
@ -320,6 +320,19 @@ static int dlpar_remove_device_tree_lmb(struct of_drconf_cell *lmb)
|
|||
return dlpar_update_device_tree_lmb(lmb);
|
||||
}
|
||||
|
||||
static struct memory_block *lmb_to_memblock(struct of_drconf_cell *lmb)
|
||||
{
|
||||
unsigned long section_nr;
|
||||
struct mem_section *mem_sect;
|
||||
struct memory_block *mem_block;
|
||||
|
||||
section_nr = pfn_to_section_nr(PFN_DOWN(lmb->base_addr));
|
||||
mem_sect = __nr_to_section(section_nr);
|
||||
|
||||
mem_block = find_memory_block(mem_sect);
|
||||
return mem_block;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTREMOVE
|
||||
static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size)
|
||||
{
|
||||
|
@ -407,19 +420,6 @@ static bool lmb_is_removable(struct of_drconf_cell *lmb)
|
|||
|
||||
static int dlpar_add_lmb(struct of_drconf_cell *);
|
||||
|
||||
static struct memory_block *lmb_to_memblock(struct of_drconf_cell *lmb)
|
||||
{
|
||||
unsigned long section_nr;
|
||||
struct mem_section *mem_sect;
|
||||
struct memory_block *mem_block;
|
||||
|
||||
section_nr = pfn_to_section_nr(PFN_DOWN(lmb->base_addr));
|
||||
mem_sect = __nr_to_section(section_nr);
|
||||
|
||||
mem_block = find_memory_block(mem_sect);
|
||||
return mem_block;
|
||||
}
|
||||
|
||||
static int dlpar_remove_lmb(struct of_drconf_cell *lmb)
|
||||
{
|
||||
struct memory_block *mem_block;
|
||||
|
@ -601,6 +601,94 @@ static int dlpar_memory_readd_by_index(u32 drc_index, struct property *prop)
|
|||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index,
|
||||
struct property *prop)
|
||||
{
|
||||
struct of_drconf_cell *lmbs;
|
||||
u32 num_lmbs, *p;
|
||||
int i, rc, start_lmb_found;
|
||||
int lmbs_available = 0, start_index = 0, end_index;
|
||||
|
||||
pr_info("Attempting to hot-remove %u LMB(s) at %x\n",
|
||||
lmbs_to_remove, drc_index);
|
||||
|
||||
if (lmbs_to_remove == 0)
|
||||
return -EINVAL;
|
||||
|
||||
p = prop->value;
|
||||
num_lmbs = *p++;
|
||||
lmbs = (struct of_drconf_cell *)p;
|
||||
start_lmb_found = 0;
|
||||
|
||||
/* Navigate to drc_index */
|
||||
while (start_index < num_lmbs) {
|
||||
if (lmbs[start_index].drc_index == drc_index) {
|
||||
start_lmb_found = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
start_index++;
|
||||
}
|
||||
|
||||
if (!start_lmb_found)
|
||||
return -EINVAL;
|
||||
|
||||
end_index = start_index + lmbs_to_remove;
|
||||
|
||||
/* Validate that there are enough LMBs to satisfy the request */
|
||||
for (i = start_index; i < end_index; i++) {
|
||||
if (lmbs[i].flags & DRCONF_MEM_RESERVED)
|
||||
break;
|
||||
|
||||
lmbs_available++;
|
||||
}
|
||||
|
||||
if (lmbs_available < lmbs_to_remove)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = start_index; i < end_index; i++) {
|
||||
if (!(lmbs[i].flags & DRCONF_MEM_ASSIGNED))
|
||||
continue;
|
||||
|
||||
rc = dlpar_remove_lmb(&lmbs[i]);
|
||||
if (rc)
|
||||
break;
|
||||
|
||||
lmbs[i].reserved = 1;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
pr_err("Memory indexed-count-remove failed, adding any removed LMBs\n");
|
||||
|
||||
for (i = start_index; i < end_index; i++) {
|
||||
if (!lmbs[i].reserved)
|
||||
continue;
|
||||
|
||||
rc = dlpar_add_lmb(&lmbs[i]);
|
||||
if (rc)
|
||||
pr_err("Failed to add LMB, drc index %x\n",
|
||||
be32_to_cpu(lmbs[i].drc_index));
|
||||
|
||||
lmbs[i].reserved = 0;
|
||||
}
|
||||
rc = -EINVAL;
|
||||
} else {
|
||||
for (i = start_index; i < end_index; i++) {
|
||||
if (!lmbs[i].reserved)
|
||||
continue;
|
||||
|
||||
dlpar_release_drc(lmbs[i].drc_index);
|
||||
pr_info("Memory at %llx (drc index %x) was hot-removed\n",
|
||||
lmbs[i].base_addr, lmbs[i].drc_index);
|
||||
|
||||
lmbs[i].reserved = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#else
|
||||
static inline int pseries_remove_memblock(unsigned long base,
|
||||
unsigned int memblock_size)
|
||||
|
@ -628,9 +716,32 @@ static int dlpar_memory_remove_by_index(u32 drc_index, struct property *prop)
|
|||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static int dlpar_memory_readd_by_index(u32 drc_index, struct property *prop)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index,
|
||||
struct property *prop)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif /* CONFIG_MEMORY_HOTREMOVE */
|
||||
|
||||
static int dlpar_online_lmb(struct of_drconf_cell *lmb)
|
||||
{
|
||||
struct memory_block *mem_block;
|
||||
int rc;
|
||||
|
||||
mem_block = lmb_to_memblock(lmb);
|
||||
if (!mem_block)
|
||||
return -EINVAL;
|
||||
|
||||
rc = device_online(&mem_block->dev);
|
||||
put_device(&mem_block->dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dlpar_add_lmb(struct of_drconf_cell *lmb)
|
||||
{
|
||||
unsigned long block_sz;
|
||||
|
@ -654,10 +765,18 @@ static int dlpar_add_lmb(struct of_drconf_cell *lmb)
|
|||
|
||||
/* Add the memory */
|
||||
rc = add_memory(nid, lmb->base_addr, block_sz);
|
||||
if (rc)
|
||||
if (rc) {
|
||||
dlpar_remove_device_tree_lmb(lmb);
|
||||
else
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = dlpar_online_lmb(lmb);
|
||||
if (rc) {
|
||||
remove_memory(nid, lmb->base_addr, block_sz);
|
||||
dlpar_remove_device_tree_lmb(lmb);
|
||||
} else {
|
||||
lmb->flags |= DRCONF_MEM_ASSIGNED;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -776,6 +895,97 @@ static int dlpar_memory_add_by_index(u32 drc_index, struct property *prop)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int dlpar_memory_add_by_ic(u32 lmbs_to_add, u32 drc_index,
|
||||
struct property *prop)
|
||||
{
|
||||
struct of_drconf_cell *lmbs;
|
||||
u32 num_lmbs, *p;
|
||||
int i, rc, start_lmb_found;
|
||||
int lmbs_available = 0, start_index = 0, end_index;
|
||||
|
||||
pr_info("Attempting to hot-add %u LMB(s) at index %x\n",
|
||||
lmbs_to_add, drc_index);
|
||||
|
||||
if (lmbs_to_add == 0)
|
||||
return -EINVAL;
|
||||
|
||||
p = prop->value;
|
||||
num_lmbs = *p++;
|
||||
lmbs = (struct of_drconf_cell *)p;
|
||||
start_lmb_found = 0;
|
||||
|
||||
/* Navigate to drc_index */
|
||||
while (start_index < num_lmbs) {
|
||||
if (lmbs[start_index].drc_index == drc_index) {
|
||||
start_lmb_found = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
start_index++;
|
||||
}
|
||||
|
||||
if (!start_lmb_found)
|
||||
return -EINVAL;
|
||||
|
||||
end_index = start_index + lmbs_to_add;
|
||||
|
||||
/* Validate that the LMBs in this range are not reserved */
|
||||
for (i = start_index; i < end_index; i++) {
|
||||
if (lmbs[i].flags & DRCONF_MEM_RESERVED)
|
||||
break;
|
||||
|
||||
lmbs_available++;
|
||||
}
|
||||
|
||||
if (lmbs_available < lmbs_to_add)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = start_index; i < end_index; i++) {
|
||||
if (lmbs[i].flags & DRCONF_MEM_ASSIGNED)
|
||||
continue;
|
||||
|
||||
rc = dlpar_acquire_drc(lmbs[i].drc_index);
|
||||
if (rc)
|
||||
break;
|
||||
|
||||
rc = dlpar_add_lmb(&lmbs[i]);
|
||||
if (rc) {
|
||||
dlpar_release_drc(lmbs[i].drc_index);
|
||||
break;
|
||||
}
|
||||
|
||||
lmbs[i].reserved = 1;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
pr_err("Memory indexed-count-add failed, removing any added LMBs\n");
|
||||
|
||||
for (i = start_index; i < end_index; i++) {
|
||||
if (!lmbs[i].reserved)
|
||||
continue;
|
||||
|
||||
rc = dlpar_remove_lmb(&lmbs[i]);
|
||||
if (rc)
|
||||
pr_err("Failed to remove LMB, drc index %x\n",
|
||||
be32_to_cpu(lmbs[i].drc_index));
|
||||
else
|
||||
dlpar_release_drc(lmbs[i].drc_index);
|
||||
}
|
||||
rc = -EINVAL;
|
||||
} else {
|
||||
for (i = start_index; i < end_index; i++) {
|
||||
if (!lmbs[i].reserved)
|
||||
continue;
|
||||
|
||||
pr_info("Memory at %llx (drc index %x) was hot-added\n",
|
||||
lmbs[i].base_addr, lmbs[i].drc_index);
|
||||
lmbs[i].reserved = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
|
||||
{
|
||||
struct device_node *dn;
|
||||
|
@ -783,9 +993,6 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
|
|||
u32 count, drc_index;
|
||||
int rc;
|
||||
|
||||
count = hp_elog->_drc_u.drc_count;
|
||||
drc_index = hp_elog->_drc_u.drc_index;
|
||||
|
||||
lock_device_hotplug();
|
||||
|
||||
dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
|
||||
|
@ -802,22 +1009,39 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
|
|||
|
||||
switch (hp_elog->action) {
|
||||
case PSERIES_HP_ELOG_ACTION_ADD:
|
||||
if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT)
|
||||
if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT) {
|
||||
count = hp_elog->_drc_u.drc_count;
|
||||
rc = dlpar_memory_add_by_count(count, prop);
|
||||
else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX)
|
||||
} else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX) {
|
||||
drc_index = hp_elog->_drc_u.drc_index;
|
||||
rc = dlpar_memory_add_by_index(drc_index, prop);
|
||||
else
|
||||
} else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_IC) {
|
||||
count = hp_elog->_drc_u.ic.count;
|
||||
drc_index = hp_elog->_drc_u.ic.index;
|
||||
rc = dlpar_memory_add_by_ic(count, drc_index, prop);
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
break;
|
||||
case PSERIES_HP_ELOG_ACTION_REMOVE:
|
||||
if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT)
|
||||
if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT) {
|
||||
count = hp_elog->_drc_u.drc_count;
|
||||
rc = dlpar_memory_remove_by_count(count, prop);
|
||||
else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX)
|
||||
} else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX) {
|
||||
drc_index = hp_elog->_drc_u.drc_index;
|
||||
rc = dlpar_memory_remove_by_index(drc_index, prop);
|
||||
else
|
||||
} else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_IC) {
|
||||
count = hp_elog->_drc_u.ic.count;
|
||||
drc_index = hp_elog->_drc_u.ic.index;
|
||||
rc = dlpar_memory_remove_by_ic(count, drc_index, prop);
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
break;
|
||||
case PSERIES_HP_ELOG_ACTION_READD:
|
||||
drc_index = hp_elog->_drc_u.drc_index;
|
||||
rc = dlpar_memory_readd_by_index(drc_index, prop);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ppc-dis.c -- Disassemble PowerPC instructions
|
||||
Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 1994-2016 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Cygnus Support
|
||||
|
||||
This file is part of GDB, GAS, and the GNU binutils.
|
||||
|
@ -26,57 +25,94 @@ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, US
|
|||
#include "ppc.h"
|
||||
#include "dis-asm.h"
|
||||
|
||||
/* Print a PowerPC or POWER instruction. */
|
||||
/* This file provides several disassembler functions, all of which use
|
||||
the disassembler interface defined in dis-asm.h. Several functions
|
||||
are provided because this file handles disassembly for the PowerPC
|
||||
in both big and little endian mode and also for the POWER (RS/6000)
|
||||
chip. */
|
||||
|
||||
int
|
||||
print_insn_powerpc (unsigned long insn, unsigned long memaddr)
|
||||
/* Extract the operand value from the PowerPC or POWER instruction. */
|
||||
|
||||
static long
|
||||
operand_value_powerpc (const struct powerpc_operand *operand,
|
||||
unsigned long insn, ppc_cpu_t dialect)
|
||||
{
|
||||
long value;
|
||||
int invalid;
|
||||
/* Extract the value from the instruction. */
|
||||
if (operand->extract)
|
||||
value = (*operand->extract) (insn, dialect, &invalid);
|
||||
else
|
||||
{
|
||||
if (operand->shift >= 0)
|
||||
value = (insn >> operand->shift) & operand->bitm;
|
||||
else
|
||||
value = (insn << -operand->shift) & operand->bitm;
|
||||
if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
|
||||
{
|
||||
/* BITM is always some number of zeros followed by some
|
||||
number of ones, followed by some number of zeros. */
|
||||
unsigned long top = operand->bitm;
|
||||
/* top & -top gives the rightmost 1 bit, so this
|
||||
fills in any trailing zeros. */
|
||||
top |= (top & -top) - 1;
|
||||
top &= ~(top >> 1);
|
||||
value = (value ^ top) - top;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Determine whether the optional operand(s) should be printed. */
|
||||
|
||||
static int
|
||||
skip_optional_operands (const unsigned char *opindex,
|
||||
unsigned long insn, ppc_cpu_t dialect)
|
||||
{
|
||||
const struct powerpc_operand *operand;
|
||||
|
||||
for (; *opindex != 0; opindex++)
|
||||
{
|
||||
operand = &powerpc_operands[*opindex];
|
||||
if ((operand->flags & PPC_OPERAND_NEXT) != 0
|
||||
|| ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
|
||||
&& operand_value_powerpc (operand, insn, dialect) !=
|
||||
ppc_optional_operand_value (operand)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Find a match for INSN in the opcode table, given machine DIALECT.
|
||||
A DIALECT of -1 is special, matching all machine opcode variations. */
|
||||
|
||||
static const struct powerpc_opcode *
|
||||
lookup_powerpc (unsigned long insn, ppc_cpu_t dialect)
|
||||
{
|
||||
const struct powerpc_opcode *opcode;
|
||||
const struct powerpc_opcode *opcode_end;
|
||||
unsigned long op;
|
||||
int dialect;
|
||||
|
||||
dialect = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON
|
||||
| PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC;
|
||||
|
||||
if (cpu_has_feature(CPU_FTRS_POWER5))
|
||||
dialect |= PPC_OPCODE_POWER5;
|
||||
|
||||
if (cpu_has_feature(CPU_FTRS_CELL))
|
||||
dialect |= PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC;
|
||||
|
||||
if (cpu_has_feature(CPU_FTRS_POWER6))
|
||||
dialect |= PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC;
|
||||
|
||||
/* Get the major opcode of the instruction. */
|
||||
op = PPC_OP (insn);
|
||||
|
||||
/* Find the first match in the opcode table. We could speed this up
|
||||
a bit by doing a binary search on the major opcode. */
|
||||
opcode_end = powerpc_opcodes + powerpc_num_opcodes;
|
||||
again:
|
||||
for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
|
||||
/* Find the first match in the opcode table for this major opcode. */
|
||||
for (opcode = powerpc_opcodes; opcode < opcode_end; ++opcode)
|
||||
{
|
||||
unsigned long table_op;
|
||||
const unsigned char *opindex;
|
||||
const struct powerpc_operand *operand;
|
||||
int invalid;
|
||||
int need_comma;
|
||||
int need_paren;
|
||||
|
||||
table_op = PPC_OP (opcode->opcode);
|
||||
if (op < table_op)
|
||||
break;
|
||||
if (op > table_op)
|
||||
continue;
|
||||
|
||||
if ((insn & opcode->mask) != opcode->opcode
|
||||
|| (opcode->flags & dialect) == 0)
|
||||
|| (dialect != (ppc_cpu_t) -1
|
||||
&& ((opcode->flags & dialect) == 0
|
||||
|| (opcode->deprecated & dialect) != 0)))
|
||||
continue;
|
||||
|
||||
/* Make two passes over the operands. First see if any of them
|
||||
have extraction functions, and, if they do, make sure the
|
||||
instruction is valid. */
|
||||
/* Check validity of operands. */
|
||||
invalid = 0;
|
||||
for (opindex = opcode->operands; *opindex != 0; opindex++)
|
||||
{
|
||||
|
@ -87,14 +123,77 @@ print_insn_powerpc (unsigned long insn, unsigned long memaddr)
|
|||
if (invalid)
|
||||
continue;
|
||||
|
||||
/* The instruction is valid. */
|
||||
printf("%s", opcode->name);
|
||||
return opcode;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Print a PowerPC or POWER instruction. */
|
||||
|
||||
int print_insn_powerpc (unsigned long insn, unsigned long memaddr)
|
||||
{
|
||||
const struct powerpc_opcode *opcode;
|
||||
bool insn_is_short;
|
||||
ppc_cpu_t dialect;
|
||||
|
||||
dialect = PPC_OPCODE_PPC | PPC_OPCODE_COMMON
|
||||
| PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC;
|
||||
|
||||
if (cpu_has_feature(CPU_FTRS_POWER5))
|
||||
dialect |= PPC_OPCODE_POWER5;
|
||||
|
||||
if (cpu_has_feature(CPU_FTRS_CELL))
|
||||
dialect |= (PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC);
|
||||
|
||||
if (cpu_has_feature(CPU_FTRS_POWER6))
|
||||
dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC);
|
||||
|
||||
if (cpu_has_feature(CPU_FTRS_POWER7))
|
||||
dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
|
||||
| PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX);
|
||||
|
||||
if (cpu_has_feature(CPU_FTRS_POWER8))
|
||||
dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
|
||||
| PPC_OPCODE_POWER8 | PPC_OPCODE_HTM
|
||||
| PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX);
|
||||
|
||||
if (cpu_has_feature(CPU_FTRS_POWER9))
|
||||
dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
|
||||
| PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9 | PPC_OPCODE_HTM
|
||||
| PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2
|
||||
| PPC_OPCODE_VSX | PPC_OPCODE_VSX3),
|
||||
|
||||
/* Get the major opcode of the insn. */
|
||||
opcode = NULL;
|
||||
insn_is_short = false;
|
||||
|
||||
if (opcode == NULL)
|
||||
opcode = lookup_powerpc (insn, dialect);
|
||||
if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
|
||||
opcode = lookup_powerpc (insn, (ppc_cpu_t) -1);
|
||||
|
||||
if (opcode != NULL)
|
||||
{
|
||||
const unsigned char *opindex;
|
||||
const struct powerpc_operand *operand;
|
||||
int need_comma;
|
||||
int need_paren;
|
||||
int skip_optional;
|
||||
|
||||
if (opcode->operands[0] != 0)
|
||||
printf("\t");
|
||||
printf("%-7s ", opcode->name);
|
||||
else
|
||||
printf("%s", opcode->name);
|
||||
|
||||
if (insn_is_short)
|
||||
/* The operands will be fetched out of the 16-bit instruction. */
|
||||
insn >>= 16;
|
||||
|
||||
/* Now extract and print the operands. */
|
||||
need_comma = 0;
|
||||
need_paren = 0;
|
||||
skip_optional = -1;
|
||||
for (opindex = opcode->operands; *opindex != 0; opindex++)
|
||||
{
|
||||
long value;
|
||||
|
@ -107,23 +206,18 @@ print_insn_powerpc (unsigned long insn, unsigned long memaddr)
|
|||
if ((operand->flags & PPC_OPERAND_FAKE) != 0)
|
||||
continue;
|
||||
|
||||
/* Extract the value from the instruction. */
|
||||
if (operand->extract)
|
||||
value = (*operand->extract) (insn, dialect, &invalid);
|
||||
else
|
||||
/* If all of the optional operands have the value zero,
|
||||
then don't print any of them. */
|
||||
if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
|
||||
{
|
||||
value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
|
||||
if ((operand->flags & PPC_OPERAND_SIGNED) != 0
|
||||
&& (value & (1 << (operand->bits - 1))) != 0)
|
||||
value -= 1 << operand->bits;
|
||||
if (skip_optional < 0)
|
||||
skip_optional = skip_optional_operands (opindex, insn,
|
||||
dialect);
|
||||
if (skip_optional)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the operand is optional, and the value is zero, don't
|
||||
print anything. */
|
||||
if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
|
||||
&& (operand->flags & PPC_OPERAND_NEXT) == 0
|
||||
&& value == 0)
|
||||
continue;
|
||||
value = operand_value_powerpc (operand, insn, dialect);
|
||||
|
||||
if (need_comma)
|
||||
{
|
||||
|
@ -139,30 +233,38 @@ print_insn_powerpc (unsigned long insn, unsigned long memaddr)
|
|||
printf("f%ld", value);
|
||||
else if ((operand->flags & PPC_OPERAND_VR) != 0)
|
||||
printf("v%ld", value);
|
||||
else if ((operand->flags & PPC_OPERAND_VSR) != 0)
|
||||
printf("vs%ld", value);
|
||||
else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
|
||||
print_address (memaddr + value);
|
||||
print_address(memaddr + value);
|
||||
else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
|
||||
print_address (value & 0xffffffff);
|
||||
else if ((operand->flags & PPC_OPERAND_CR) == 0
|
||||
|| (dialect & PPC_OPCODE_PPC) == 0)
|
||||
print_address(value & 0xffffffff);
|
||||
else if ((operand->flags & PPC_OPERAND_FSL) != 0)
|
||||
printf("fsl%ld", value);
|
||||
else if ((operand->flags & PPC_OPERAND_FCR) != 0)
|
||||
printf("fcr%ld", value);
|
||||
else if ((operand->flags & PPC_OPERAND_UDI) != 0)
|
||||
printf("%ld", value);
|
||||
else
|
||||
else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
|
||||
&& (((dialect & PPC_OPCODE_PPC) != 0)
|
||||
|| ((dialect & PPC_OPCODE_VLE) != 0)))
|
||||
printf("cr%ld", value);
|
||||
else if (((operand->flags & PPC_OPERAND_CR_BIT) != 0)
|
||||
&& (((dialect & PPC_OPCODE_PPC) != 0)
|
||||
|| ((dialect & PPC_OPCODE_VLE) != 0)))
|
||||
{
|
||||
if (operand->bits == 3)
|
||||
printf("cr%ld", value);
|
||||
else
|
||||
{
|
||||
static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
|
||||
int cr;
|
||||
int cc;
|
||||
static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
|
||||
int cr;
|
||||
int cc;
|
||||
|
||||
cr = value >> 2;
|
||||
if (cr != 0)
|
||||
printf("4*cr%d+", cr);
|
||||
cc = value & 3;
|
||||
printf("%s", cbnames[cc]);
|
||||
}
|
||||
cr = value >> 2;
|
||||
if (cr != 0)
|
||||
printf("4*cr%d+", cr);
|
||||
cc = value & 3;
|
||||
printf("%s", cbnames[cc]);
|
||||
}
|
||||
else
|
||||
printf("%d", (int) value);
|
||||
|
||||
if (need_paren)
|
||||
{
|
||||
|
@ -179,14 +281,16 @@ print_insn_powerpc (unsigned long insn, unsigned long memaddr)
|
|||
}
|
||||
}
|
||||
|
||||
/* We have found and printed an instruction; return. */
|
||||
return 4;
|
||||
}
|
||||
|
||||
if ((dialect & PPC_OPCODE_ANY) != 0)
|
||||
{
|
||||
dialect = ~PPC_OPCODE_ANY;
|
||||
goto again;
|
||||
/* We have found and printed an instruction.
|
||||
If it was a short VLE instruction we have more to do. */
|
||||
if (insn_is_short)
|
||||
{
|
||||
memaddr += 2;
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
/* Otherwise, return. */
|
||||
return 4;
|
||||
}
|
||||
|
||||
/* We could not find a match. */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,5 @@
|
|||
/* ppc.h -- Header file for PowerPC opcode table
|
||||
Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 1994-2016 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Cygnus Support
|
||||
|
||||
This file is part of GDB, GAS, and the GNU binutils.
|
||||
|
@ -22,6 +21,12 @@ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, US
|
|||
#ifndef PPC_H
|
||||
#define PPC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint64_t ppc_cpu_t;
|
||||
|
||||
/* The opcode table is an array of struct powerpc_opcode. */
|
||||
|
||||
struct powerpc_opcode
|
||||
|
@ -42,7 +47,12 @@ struct powerpc_opcode
|
|||
/* One bit flags for the opcode. These are used to indicate which
|
||||
specific processors support the instructions. The defined values
|
||||
are listed below. */
|
||||
unsigned long flags;
|
||||
ppc_cpu_t flags;
|
||||
|
||||
/* One bit flags for the opcode. These are used to indicate which
|
||||
specific processors no longer support the instructions. The defined
|
||||
values are listed below. */
|
||||
ppc_cpu_t deprecated;
|
||||
|
||||
/* An array of operand codes. Each code is an index into the
|
||||
operand table. They appear in the order which the operands must
|
||||
|
@ -55,6 +65,8 @@ struct powerpc_opcode
|
|||
instructions. */
|
||||
extern const struct powerpc_opcode powerpc_opcodes[];
|
||||
extern const int powerpc_num_opcodes;
|
||||
extern const struct powerpc_opcode vle_opcodes[];
|
||||
extern const int vle_num_opcodes;
|
||||
|
||||
/* Values defined for the flags field of a struct powerpc_opcode. */
|
||||
|
||||
|
@ -67,106 +79,178 @@ extern const int powerpc_num_opcodes;
|
|||
/* Opcode is defined for the POWER2 (Rios 2) architecture. */
|
||||
#define PPC_OPCODE_POWER2 4
|
||||
|
||||
/* Opcode is only defined on 32 bit architectures. */
|
||||
#define PPC_OPCODE_32 8
|
||||
|
||||
/* Opcode is only defined on 64 bit architectures. */
|
||||
#define PPC_OPCODE_64 0x10
|
||||
|
||||
/* Opcode is supported by the Motorola PowerPC 601 processor. The 601
|
||||
is assumed to support all PowerPC (PPC_OPCODE_PPC) instructions,
|
||||
but it also supports many additional POWER instructions. */
|
||||
#define PPC_OPCODE_601 0x20
|
||||
#define PPC_OPCODE_601 8
|
||||
|
||||
/* Opcode is supported in both the Power and PowerPC architectures
|
||||
(ie, compiler's -mcpu=common or assembler's -mcom). */
|
||||
#define PPC_OPCODE_COMMON 0x40
|
||||
(ie, compiler's -mcpu=common or assembler's -mcom). More than just
|
||||
the intersection of PPC_OPCODE_PPC with the union of PPC_OPCODE_POWER
|
||||
and PPC_OPCODE_POWER2 because many instructions changed mnemonics
|
||||
between POWER and POWERPC. */
|
||||
#define PPC_OPCODE_COMMON 0x10
|
||||
|
||||
/* Opcode is supported for any Power or PowerPC platform (this is
|
||||
for the assembler's -many option, and it eliminates duplicates). */
|
||||
#define PPC_OPCODE_ANY 0x80
|
||||
#define PPC_OPCODE_ANY 0x20
|
||||
|
||||
/* Opcode is only defined on 64 bit architectures. */
|
||||
#define PPC_OPCODE_64 0x40
|
||||
|
||||
/* Opcode is supported as part of the 64-bit bridge. */
|
||||
#define PPC_OPCODE_64_BRIDGE 0x100
|
||||
#define PPC_OPCODE_64_BRIDGE 0x80
|
||||
|
||||
/* Opcode is supported by Altivec Vector Unit */
|
||||
#define PPC_OPCODE_ALTIVEC 0x200
|
||||
#define PPC_OPCODE_ALTIVEC 0x100
|
||||
|
||||
/* Opcode is supported by PowerPC 403 processor. */
|
||||
#define PPC_OPCODE_403 0x400
|
||||
#define PPC_OPCODE_403 0x200
|
||||
|
||||
/* Opcode is supported by PowerPC BookE processor. */
|
||||
#define PPC_OPCODE_BOOKE 0x800
|
||||
|
||||
/* Opcode is only supported by 64-bit PowerPC BookE processor. */
|
||||
#define PPC_OPCODE_BOOKE64 0x1000
|
||||
#define PPC_OPCODE_BOOKE 0x400
|
||||
|
||||
/* Opcode is supported by PowerPC 440 processor. */
|
||||
#define PPC_OPCODE_440 0x2000
|
||||
#define PPC_OPCODE_440 0x800
|
||||
|
||||
/* Opcode is only supported by Power4 architecture. */
|
||||
#define PPC_OPCODE_POWER4 0x4000
|
||||
#define PPC_OPCODE_POWER4 0x1000
|
||||
|
||||
/* Opcode isn't supported by Power4 architecture. */
|
||||
#define PPC_OPCODE_NOPOWER4 0x8000
|
||||
|
||||
/* Opcode is only supported by POWERPC Classic architecture. */
|
||||
#define PPC_OPCODE_CLASSIC 0x10000
|
||||
/* Opcode is only supported by Power7 architecture. */
|
||||
#define PPC_OPCODE_POWER7 0x2000
|
||||
|
||||
/* Opcode is only supported by e500x2 Core. */
|
||||
#define PPC_OPCODE_SPE 0x20000
|
||||
#define PPC_OPCODE_SPE 0x4000
|
||||
|
||||
/* Opcode is supported by e500x2 Integer select APU. */
|
||||
#define PPC_OPCODE_ISEL 0x40000
|
||||
#define PPC_OPCODE_ISEL 0x8000
|
||||
|
||||
/* Opcode is an e500 SPE floating point instruction. */
|
||||
#define PPC_OPCODE_EFS 0x80000
|
||||
#define PPC_OPCODE_EFS 0x10000
|
||||
|
||||
/* Opcode is supported by branch locking APU. */
|
||||
#define PPC_OPCODE_BRLOCK 0x100000
|
||||
#define PPC_OPCODE_BRLOCK 0x20000
|
||||
|
||||
/* Opcode is supported by performance monitor APU. */
|
||||
#define PPC_OPCODE_PMR 0x200000
|
||||
#define PPC_OPCODE_PMR 0x40000
|
||||
|
||||
/* Opcode is supported by cache locking APU. */
|
||||
#define PPC_OPCODE_CACHELCK 0x400000
|
||||
#define PPC_OPCODE_CACHELCK 0x80000
|
||||
|
||||
/* Opcode is supported by machine check APU. */
|
||||
#define PPC_OPCODE_RFMCI 0x800000
|
||||
#define PPC_OPCODE_RFMCI 0x100000
|
||||
|
||||
/* Opcode is only supported by Power5 architecture. */
|
||||
#define PPC_OPCODE_POWER5 0x1000000
|
||||
#define PPC_OPCODE_POWER5 0x200000
|
||||
|
||||
/* Opcode is supported by PowerPC e300 family. */
|
||||
#define PPC_OPCODE_E300 0x2000000
|
||||
#define PPC_OPCODE_E300 0x400000
|
||||
|
||||
/* Opcode is only supported by Power6 architecture. */
|
||||
#define PPC_OPCODE_POWER6 0x4000000
|
||||
#define PPC_OPCODE_POWER6 0x800000
|
||||
|
||||
/* Opcode is only supported by PowerPC Cell family. */
|
||||
#define PPC_OPCODE_CELL 0x8000000
|
||||
#define PPC_OPCODE_CELL 0x1000000
|
||||
|
||||
/* Opcode is supported by CPUs with paired singles support. */
|
||||
#define PPC_OPCODE_PPCPS 0x2000000
|
||||
|
||||
/* Opcode is supported by Power E500MC */
|
||||
#define PPC_OPCODE_E500MC 0x4000000
|
||||
|
||||
/* Opcode is supported by PowerPC 405 processor. */
|
||||
#define PPC_OPCODE_405 0x8000000
|
||||
|
||||
/* Opcode is supported by Vector-Scalar (VSX) Unit */
|
||||
#define PPC_OPCODE_VSX 0x10000000
|
||||
|
||||
/* Opcode is supported by A2. */
|
||||
#define PPC_OPCODE_A2 0x20000000
|
||||
|
||||
/* Opcode is supported by PowerPC 476 processor. */
|
||||
#define PPC_OPCODE_476 0x40000000
|
||||
|
||||
/* Opcode is supported by AppliedMicro Titan core */
|
||||
#define PPC_OPCODE_TITAN 0x80000000
|
||||
|
||||
/* Opcode which is supported by the e500 family */
|
||||
#define PPC_OPCODE_E500 0x100000000ull
|
||||
|
||||
/* Opcode is supported by Extended Altivec Vector Unit */
|
||||
#define PPC_OPCODE_ALTIVEC2 0x200000000ull
|
||||
|
||||
/* Opcode is supported by Power E6500 */
|
||||
#define PPC_OPCODE_E6500 0x400000000ull
|
||||
|
||||
/* Opcode is supported by Thread management APU */
|
||||
#define PPC_OPCODE_TMR 0x800000000ull
|
||||
|
||||
/* Opcode which is supported by the VLE extension. */
|
||||
#define PPC_OPCODE_VLE 0x1000000000ull
|
||||
|
||||
/* Opcode is only supported by Power8 architecture. */
|
||||
#define PPC_OPCODE_POWER8 0x2000000000ull
|
||||
|
||||
/* Opcode which is supported by the Hardware Transactional Memory extension. */
|
||||
/* Currently, this is the same as the POWER8 mask. If another cpu comes out
|
||||
that isn't a superset of POWER8, we can define this to its own mask. */
|
||||
#define PPC_OPCODE_HTM PPC_OPCODE_POWER8
|
||||
|
||||
/* Opcode is supported by ppc750cl. */
|
||||
#define PPC_OPCODE_750 0x4000000000ull
|
||||
|
||||
/* Opcode is supported by ppc7450. */
|
||||
#define PPC_OPCODE_7450 0x8000000000ull
|
||||
|
||||
/* Opcode is supported by ppc821/850/860. */
|
||||
#define PPC_OPCODE_860 0x10000000000ull
|
||||
|
||||
/* Opcode is only supported by Power9 architecture. */
|
||||
#define PPC_OPCODE_POWER9 0x20000000000ull
|
||||
|
||||
/* Opcode is supported by Vector-Scalar (VSX) Unit from ISA 2.08. */
|
||||
#define PPC_OPCODE_VSX3 0x40000000000ull
|
||||
|
||||
/* Opcode is supported by e200z4. */
|
||||
#define PPC_OPCODE_E200Z4 0x80000000000ull
|
||||
|
||||
/* A macro to extract the major opcode from an instruction. */
|
||||
#define PPC_OP(i) (((i) >> 26) & 0x3f)
|
||||
|
||||
/* A macro to determine if the instruction is a 2-byte VLE insn. */
|
||||
#define PPC_OP_SE_VLE(m) ((m) <= 0xffff)
|
||||
|
||||
/* A macro to extract the major opcode from a VLE instruction. */
|
||||
#define VLE_OP(i,m) (((i) >> ((m) <= 0xffff ? 10 : 26)) & 0x3f)
|
||||
|
||||
/* A macro to convert a VLE opcode to a VLE opcode segment. */
|
||||
#define VLE_OP_TO_SEG(i) ((i) >> 1)
|
||||
|
||||
/* The operands table is an array of struct powerpc_operand. */
|
||||
|
||||
struct powerpc_operand
|
||||
{
|
||||
/* The number of bits in the operand. */
|
||||
int bits;
|
||||
/* A bitmask of bits in the operand. */
|
||||
unsigned int bitm;
|
||||
|
||||
/* How far the operand is left shifted in the instruction. */
|
||||
/* The shift operation to be applied to the operand. No shift
|
||||
is made if this is zero. For positive values, the operand
|
||||
is shifted left by SHIFT. For negative values, the operand
|
||||
is shifted right by -SHIFT. Use PPC_OPSHIFT_INV to indicate
|
||||
that BITM and SHIFT cannot be used to determine where the
|
||||
operand goes in the insn. */
|
||||
int shift;
|
||||
|
||||
/* Insertion function. This is used by the assembler. To insert an
|
||||
operand value into an instruction, check this field.
|
||||
|
||||
If it is NULL, execute
|
||||
i |= (op & ((1 << o->bits) - 1)) << o->shift;
|
||||
if (o->shift >= 0)
|
||||
i |= (op & o->bitm) << o->shift;
|
||||
else
|
||||
i |= (op & o->bitm) >> -o->shift;
|
||||
(i is the instruction which we are filling in, o is a pointer to
|
||||
this structure, and op is the opcode value; this assumes twos
|
||||
complement arithmetic).
|
||||
this structure, and op is the operand value).
|
||||
|
||||
If this field is not NULL, then simply call it with the
|
||||
instruction and the operand value. It will return the new value
|
||||
|
@ -176,18 +260,20 @@ struct powerpc_operand
|
|||
operand value is legal, *ERRMSG will be unchanged (most operands
|
||||
can accept any value). */
|
||||
unsigned long (*insert)
|
||||
(unsigned long instruction, long op, int dialect, const char **errmsg);
|
||||
(unsigned long instruction, long op, ppc_cpu_t dialect, const char **errmsg);
|
||||
|
||||
/* Extraction function. This is used by the disassembler. To
|
||||
extract this operand type from an instruction, check this field.
|
||||
|
||||
If it is NULL, compute
|
||||
op = ((i) >> o->shift) & ((1 << o->bits) - 1);
|
||||
if ((o->flags & PPC_OPERAND_SIGNED) != 0
|
||||
&& (op & (1 << (o->bits - 1))) != 0)
|
||||
op -= 1 << o->bits;
|
||||
if (o->shift >= 0)
|
||||
op = (i >> o->shift) & o->bitm;
|
||||
else
|
||||
op = (i << -o->shift) & o->bitm;
|
||||
if ((o->flags & PPC_OPERAND_SIGNED) != 0)
|
||||
sign_extend (op);
|
||||
(i is the instruction, o is a pointer to this structure, and op
|
||||
is the result; this assumes twos complement arithmetic).
|
||||
is the result).
|
||||
|
||||
If this field is not NULL, then simply call it with the
|
||||
instruction value. It will return the value of the operand. If
|
||||
|
@ -195,7 +281,7 @@ struct powerpc_operand
|
|||
non-zero if this operand type can not actually be extracted from
|
||||
this operand (i.e., the instruction does not match). If the
|
||||
operand is valid, *INVALID will not be changed. */
|
||||
long (*extract) (unsigned long instruction, int dialect, int *invalid);
|
||||
long (*extract) (unsigned long instruction, ppc_cpu_t dialect, int *invalid);
|
||||
|
||||
/* One bit syntax flags. */
|
||||
unsigned long flags;
|
||||
|
@ -205,17 +291,23 @@ struct powerpc_operand
|
|||
the operands field of the powerpc_opcodes table. */
|
||||
|
||||
extern const struct powerpc_operand powerpc_operands[];
|
||||
extern const unsigned int num_powerpc_operands;
|
||||
|
||||
/* Use with the shift field of a struct powerpc_operand to indicate
|
||||
that BITM and SHIFT cannot be used to determine where the operand
|
||||
goes in the insn. */
|
||||
#define PPC_OPSHIFT_INV (-1U << 31)
|
||||
|
||||
/* Values defined for the flags field of a struct powerpc_operand. */
|
||||
|
||||
/* This operand takes signed values. */
|
||||
#define PPC_OPERAND_SIGNED (01)
|
||||
#define PPC_OPERAND_SIGNED (0x1)
|
||||
|
||||
/* This operand takes signed values, but also accepts a full positive
|
||||
range of values when running in 32 bit mode. That is, if bits is
|
||||
16, it takes any value from -0x8000 to 0xffff. In 64 bit mode,
|
||||
this flag is ignored. */
|
||||
#define PPC_OPERAND_SIGNOPT (02)
|
||||
#define PPC_OPERAND_SIGNOPT (0x2)
|
||||
|
||||
/* This operand does not actually exist in the assembler input. This
|
||||
is used to support extended mnemonics such as mr, for which two
|
||||
|
@ -223,14 +315,14 @@ extern const struct powerpc_operand powerpc_operands[];
|
|||
insert function with any op value. The disassembler should call
|
||||
the extract function, ignore the return value, and check the value
|
||||
placed in the valid argument. */
|
||||
#define PPC_OPERAND_FAKE (04)
|
||||
#define PPC_OPERAND_FAKE (0x4)
|
||||
|
||||
/* The next operand should be wrapped in parentheses rather than
|
||||
separated from this one by a comma. This is used for the load and
|
||||
store instructions which want their operands to look like
|
||||
reg,displacement(reg)
|
||||
*/
|
||||
#define PPC_OPERAND_PARENS (010)
|
||||
#define PPC_OPERAND_PARENS (0x8)
|
||||
|
||||
/* This operand may use the symbolic names for the CR fields, which
|
||||
are
|
||||
|
@ -239,26 +331,26 @@ extern const struct powerpc_operand powerpc_operands[];
|
|||
cr4 4 cr5 5 cr6 6 cr7 7
|
||||
These may be combined arithmetically, as in cr2*4+gt. These are
|
||||
only supported on the PowerPC, not the POWER. */
|
||||
#define PPC_OPERAND_CR (020)
|
||||
#define PPC_OPERAND_CR_BIT (0x10)
|
||||
|
||||
/* This operand names a register. The disassembler uses this to print
|
||||
register names with a leading 'r'. */
|
||||
#define PPC_OPERAND_GPR (040)
|
||||
#define PPC_OPERAND_GPR (0x20)
|
||||
|
||||
/* Like PPC_OPERAND_GPR, but don't print a leading 'r' for r0. */
|
||||
#define PPC_OPERAND_GPR_0 (0100)
|
||||
#define PPC_OPERAND_GPR_0 (0x40)
|
||||
|
||||
/* This operand names a floating point register. The disassembler
|
||||
prints these with a leading 'f'. */
|
||||
#define PPC_OPERAND_FPR (0200)
|
||||
#define PPC_OPERAND_FPR (0x80)
|
||||
|
||||
/* This operand is a relative branch displacement. The disassembler
|
||||
prints these symbolically if possible. */
|
||||
#define PPC_OPERAND_RELATIVE (0400)
|
||||
#define PPC_OPERAND_RELATIVE (0x100)
|
||||
|
||||
/* This operand is an absolute branch address. The disassembler
|
||||
prints these symbolically if possible. */
|
||||
#define PPC_OPERAND_ABSOLUTE (01000)
|
||||
#define PPC_OPERAND_ABSOLUTE (0x200)
|
||||
|
||||
/* This operand is optional, and is zero if omitted. This is used for
|
||||
example, in the optional BF field in the comparison instructions. The
|
||||
|
@ -266,7 +358,7 @@ extern const struct powerpc_operand powerpc_operands[];
|
|||
and the number of operands remaining for the opcode, and decide
|
||||
whether this operand is present or not. The disassembler should
|
||||
print this operand out only if it is not zero. */
|
||||
#define PPC_OPERAND_OPTIONAL (02000)
|
||||
#define PPC_OPERAND_OPTIONAL (0x400)
|
||||
|
||||
/* This flag is only used with PPC_OPERAND_OPTIONAL. If this operand
|
||||
is omitted, then for the next operand use this operand value plus
|
||||
|
@ -274,24 +366,48 @@ extern const struct powerpc_operand powerpc_operands[];
|
|||
hack is needed because the Power rotate instructions can take
|
||||
either 4 or 5 operands. The disassembler should print this operand
|
||||
out regardless of the PPC_OPERAND_OPTIONAL field. */
|
||||
#define PPC_OPERAND_NEXT (04000)
|
||||
#define PPC_OPERAND_NEXT (0x800)
|
||||
|
||||
/* This operand should be regarded as a negative number for the
|
||||
purposes of overflow checking (i.e., the normal most negative
|
||||
number is disallowed and one more than the normal most positive
|
||||
number is allowed). This flag will only be set for a signed
|
||||
operand. */
|
||||
#define PPC_OPERAND_NEGATIVE (010000)
|
||||
#define PPC_OPERAND_NEGATIVE (0x1000)
|
||||
|
||||
/* This operand names a vector unit register. The disassembler
|
||||
prints these with a leading 'v'. */
|
||||
#define PPC_OPERAND_VR (020000)
|
||||
#define PPC_OPERAND_VR (0x2000)
|
||||
|
||||
/* This operand is for the DS field in a DS form instruction. */
|
||||
#define PPC_OPERAND_DS (040000)
|
||||
#define PPC_OPERAND_DS (0x4000)
|
||||
|
||||
/* This operand is for the DQ field in a DQ form instruction. */
|
||||
#define PPC_OPERAND_DQ (0100000)
|
||||
#define PPC_OPERAND_DQ (0x8000)
|
||||
|
||||
/* Valid range of operand is 0..n rather than 0..n-1. */
|
||||
#define PPC_OPERAND_PLUS1 (0x10000)
|
||||
|
||||
/* Xilinx APU and FSL related operands */
|
||||
#define PPC_OPERAND_FSL (0x20000)
|
||||
#define PPC_OPERAND_FCR (0x40000)
|
||||
#define PPC_OPERAND_UDI (0x80000)
|
||||
|
||||
/* This operand names a vector-scalar unit register. The disassembler
|
||||
prints these with a leading 'vs'. */
|
||||
#define PPC_OPERAND_VSR (0x100000)
|
||||
|
||||
/* This is a CR FIELD that does not use symbolic names. */
|
||||
#define PPC_OPERAND_CR_REG (0x200000)
|
||||
|
||||
/* This flag is only used with PPC_OPERAND_OPTIONAL. If this operand
|
||||
is omitted, then the value it should use for the operand is stored
|
||||
in the SHIFT field of the immediatly following operand field. */
|
||||
#define PPC_OPERAND_OPTIONAL_VALUE (0x400000)
|
||||
|
||||
/* This flag is only used with PPC_OPERAND_OPTIONAL. The operand is
|
||||
only optional when generating 32-bit code. */
|
||||
#define PPC_OPERAND_OPTIONAL32 (0x800000)
|
||||
|
||||
/* The POWER and PowerPC assemblers use a few macros. We keep them
|
||||
with the operands table for simplicity. The macro table is an
|
||||
|
@ -308,7 +424,7 @@ struct powerpc_macro
|
|||
/* One bit flags for the opcode. These are used to indicate which
|
||||
specific processors support the instructions. The values are the
|
||||
same as those for the struct powerpc_opcode flags field. */
|
||||
unsigned long flags;
|
||||
ppc_cpu_t flags;
|
||||
|
||||
/* A format string to turn the macro into a normal instruction.
|
||||
Each %N in the string is replaced with operand number N (zero
|
||||
|
@ -319,4 +435,18 @@ struct powerpc_macro
|
|||
extern const struct powerpc_macro powerpc_macros[];
|
||||
extern const int powerpc_num_macros;
|
||||
|
||||
extern ppc_cpu_t ppc_parse_cpu (ppc_cpu_t, ppc_cpu_t *, const char *);
|
||||
|
||||
static inline long
|
||||
ppc_optional_operand_value (const struct powerpc_operand *operand)
|
||||
{
|
||||
if ((operand->flags & PPC_OPERAND_OPTIONAL_VALUE) != 0)
|
||||
return (operand+1)->shift;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PPC_H */
|
||||
|
|
|
@ -212,6 +212,10 @@ Commands:\n\
|
|||
"\
|
||||
C checksum\n\
|
||||
d dump bytes\n\
|
||||
d1 dump 1 byte values\n\
|
||||
d2 dump 2 byte values\n\
|
||||
d4 dump 4 byte values\n\
|
||||
d8 dump 8 byte values\n\
|
||||
di dump instructions\n\
|
||||
df dump float values\n\
|
||||
dd dump double values\n\
|
||||
|
@ -2334,9 +2338,42 @@ static void dump_pacas(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void dump_by_size(unsigned long addr, long count, int size)
|
||||
{
|
||||
unsigned char temp[16];
|
||||
int i, j;
|
||||
u64 val;
|
||||
|
||||
count = ALIGN(count, 16);
|
||||
|
||||
for (i = 0; i < count; i += 16, addr += 16) {
|
||||
printf(REG, addr);
|
||||
|
||||
if (mread(addr, temp, 16) != 16) {
|
||||
printf("\nFaulted reading %d bytes from 0x"REG"\n", 16, addr);
|
||||
return;
|
||||
}
|
||||
|
||||
for (j = 0; j < 16; j += size) {
|
||||
putchar(' ');
|
||||
switch (size) {
|
||||
case 1: val = temp[j]; break;
|
||||
case 2: val = *(u16 *)&temp[j]; break;
|
||||
case 4: val = *(u32 *)&temp[j]; break;
|
||||
case 8: val = *(u64 *)&temp[j]; break;
|
||||
default: val = 0;
|
||||
}
|
||||
|
||||
printf("%0*lx", size * 2, val);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump(void)
|
||||
{
|
||||
static char last[] = { "d?\n" };
|
||||
int c;
|
||||
|
||||
c = inchar();
|
||||
|
@ -2350,8 +2387,9 @@ dump(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
|
||||
if (c == '\n')
|
||||
termch = c;
|
||||
|
||||
scanhex((void *)&adrs);
|
||||
if (termch != '\n')
|
||||
termch = 0;
|
||||
|
@ -2383,9 +2421,23 @@ dump(void)
|
|||
ndump = 64;
|
||||
else if (ndump > MAX_DUMP)
|
||||
ndump = MAX_DUMP;
|
||||
prdump(adrs, ndump);
|
||||
|
||||
switch (c) {
|
||||
case '8':
|
||||
case '4':
|
||||
case '2':
|
||||
case '1':
|
||||
ndump = ALIGN(ndump, 16);
|
||||
dump_by_size(adrs, ndump, c - '0');
|
||||
last[1] = c;
|
||||
last_cmd = last;
|
||||
break;
|
||||
default:
|
||||
prdump(adrs, ndump);
|
||||
last_cmd = "d\n";
|
||||
}
|
||||
|
||||
adrs += ndump;
|
||||
last_cmd = "d\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -345,8 +345,6 @@ SECTIONS
|
|||
DISCARDS
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame)
|
||||
*(__func_stack_frame_non_standard)
|
||||
*(__unreachable)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/platform_data/x86/pmc_atom.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
@ -154,6 +155,18 @@ static void byt_i2c_setup(struct lpss_private_data *pdata)
|
|||
writel(0, pdata->mmio_base + LPSS_I2C_ENABLE);
|
||||
}
|
||||
|
||||
/* BSW PWM used for backlight control by the i915 driver */
|
||||
static struct pwm_lookup bsw_pwm_lookup[] = {
|
||||
PWM_LOOKUP_WITH_MODULE("80862288:00", 0, "0000:00:02.0",
|
||||
"pwm_backlight", 0, PWM_POLARITY_NORMAL,
|
||||
"pwm-lpss-platform"),
|
||||
};
|
||||
|
||||
static void bsw_pwm_setup(struct lpss_private_data *pdata)
|
||||
{
|
||||
pwm_add_table(bsw_pwm_lookup, ARRAY_SIZE(bsw_pwm_lookup));
|
||||
}
|
||||
|
||||
static const struct lpss_device_desc lpt_dev_desc = {
|
||||
.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR,
|
||||
.prv_offset = 0x800,
|
||||
|
@ -191,6 +204,7 @@ static const struct lpss_device_desc byt_pwm_dev_desc = {
|
|||
|
||||
static const struct lpss_device_desc bsw_pwm_dev_desc = {
|
||||
.flags = LPSS_SAVE_CTX | LPSS_NO_D3_DELAY,
|
||||
.setup = bsw_pwm_setup,
|
||||
};
|
||||
|
||||
static const struct lpss_device_desc byt_uart_dev_desc = {
|
||||
|
|
|
@ -325,6 +325,9 @@ static const struct file_operations dma_buf_fops = {
|
|||
.llseek = dma_buf_llseek,
|
||||
.poll = dma_buf_poll,
|
||||
.unlocked_ioctl = dma_buf_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = dma_buf_ioctl,
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -141,4 +141,66 @@ static const struct ast_dramstruct ast2100_dram_table_data[] = {
|
|||
{ 0xffff, 0xffffffff },
|
||||
};
|
||||
|
||||
/*
|
||||
* AST2500 DRAM settings modules
|
||||
*/
|
||||
#define REGTBL_NUM 17
|
||||
#define REGIDX_010 0
|
||||
#define REGIDX_014 1
|
||||
#define REGIDX_018 2
|
||||
#define REGIDX_020 3
|
||||
#define REGIDX_024 4
|
||||
#define REGIDX_02C 5
|
||||
#define REGIDX_030 6
|
||||
#define REGIDX_214 7
|
||||
#define REGIDX_2E0 8
|
||||
#define REGIDX_2E4 9
|
||||
#define REGIDX_2E8 10
|
||||
#define REGIDX_2EC 11
|
||||
#define REGIDX_2F0 12
|
||||
#define REGIDX_2F4 13
|
||||
#define REGIDX_2F8 14
|
||||
#define REGIDX_RFC 15
|
||||
#define REGIDX_PLL 16
|
||||
|
||||
static const u32 ast2500_ddr3_1600_timing_table[REGTBL_NUM] = {
|
||||
0x64604D38, /* 0x010 */
|
||||
0x29690599, /* 0x014 */
|
||||
0x00000300, /* 0x018 */
|
||||
0x00000000, /* 0x020 */
|
||||
0x00000000, /* 0x024 */
|
||||
0x02181E70, /* 0x02C */
|
||||
0x00000040, /* 0x030 */
|
||||
0x00000024, /* 0x214 */
|
||||
0x02001300, /* 0x2E0 */
|
||||
0x0E0000A0, /* 0x2E4 */
|
||||
0x000E001B, /* 0x2E8 */
|
||||
0x35B8C105, /* 0x2EC */
|
||||
0x08090408, /* 0x2F0 */
|
||||
0x9B000800, /* 0x2F4 */
|
||||
0x0E400A00, /* 0x2F8 */
|
||||
0x9971452F, /* tRFC */
|
||||
0x000071C1 /* PLL */
|
||||
};
|
||||
|
||||
static const u32 ast2500_ddr4_1600_timing_table[REGTBL_NUM] = {
|
||||
0x63604E37, /* 0x010 */
|
||||
0xE97AFA99, /* 0x014 */
|
||||
0x00019000, /* 0x018 */
|
||||
0x08000000, /* 0x020 */
|
||||
0x00000400, /* 0x024 */
|
||||
0x00000410, /* 0x02C */
|
||||
0x00000101, /* 0x030 */
|
||||
0x00000024, /* 0x214 */
|
||||
0x03002900, /* 0x2E0 */
|
||||
0x0E0000A0, /* 0x2E4 */
|
||||
0x000E001C, /* 0x2E8 */
|
||||
0x35B8C106, /* 0x2EC */
|
||||
0x08080607, /* 0x2F0 */
|
||||
0x9B000900, /* 0x2F4 */
|
||||
0x0E400A00, /* 0x2F8 */
|
||||
0x99714545, /* tRFC */
|
||||
0x000071C1 /* PLL */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -65,6 +65,7 @@ enum ast_chip {
|
|||
AST2150,
|
||||
AST2300,
|
||||
AST2400,
|
||||
AST2500,
|
||||
AST1180,
|
||||
};
|
||||
|
||||
|
@ -81,6 +82,7 @@ enum ast_tx_chip {
|
|||
#define AST_DRAM_1Gx32 3
|
||||
#define AST_DRAM_2Gx16 6
|
||||
#define AST_DRAM_4Gx16 7
|
||||
#define AST_DRAM_8Gx16 8
|
||||
|
||||
struct ast_fbdev;
|
||||
|
||||
|
@ -114,7 +116,11 @@ struct ast_private {
|
|||
struct ttm_bo_kmap_obj cache_kmap;
|
||||
int next_cursor;
|
||||
bool support_wide_screen;
|
||||
bool DisableP2A;
|
||||
enum {
|
||||
ast_use_p2a,
|
||||
ast_use_dt,
|
||||
ast_use_defaults
|
||||
} config_mode;
|
||||
|
||||
enum ast_tx_chip tx_chip_type;
|
||||
u8 dp501_maxclk;
|
||||
|
@ -301,8 +307,8 @@ struct ast_vbios_dclk_info {
|
|||
};
|
||||
|
||||
struct ast_vbios_mode_info {
|
||||
struct ast_vbios_stdtable *std_table;
|
||||
struct ast_vbios_enhtable *enh_table;
|
||||
const struct ast_vbios_stdtable *std_table;
|
||||
const struct ast_vbios_enhtable *enh_table;
|
||||
};
|
||||
|
||||
extern int ast_mode_init(struct drm_device *dev);
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
|
||||
#include "ast_dram_tables.h"
|
||||
|
||||
void ast_set_index_reg_mask(struct ast_private *ast,
|
||||
uint32_t base, uint8_t index,
|
||||
uint8_t mask, uint8_t val)
|
||||
|
@ -62,30 +60,99 @@ uint8_t ast_get_index_reg_mask(struct ast_private *ast,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev)
|
||||
{
|
||||
struct device_node *np = dev->pdev->dev.of_node;
|
||||
struct ast_private *ast = dev->dev_private;
|
||||
uint32_t data, jregd0, jregd1;
|
||||
|
||||
/* Defaults */
|
||||
ast->config_mode = ast_use_defaults;
|
||||
*scu_rev = 0xffffffff;
|
||||
|
||||
/* Check if we have device-tree properties */
|
||||
if (np && !of_property_read_u32(np, "aspeed,scu-revision-id",
|
||||
scu_rev)) {
|
||||
/* We do, disable P2A access */
|
||||
ast->config_mode = ast_use_dt;
|
||||
DRM_INFO("Using device-tree for configuration\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Not all families have a P2A bridge */
|
||||
if (dev->pdev->device != PCI_CHIP_AST2000)
|
||||
return;
|
||||
|
||||
/*
|
||||
* The BMC will set SCU 0x40 D[12] to 1 if the P2 bridge
|
||||
* is disabled. We force using P2A if VGA only mode bit
|
||||
* is set D[7]
|
||||
*/
|
||||
jregd0 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
|
||||
jregd1 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
|
||||
if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) {
|
||||
/* Double check it's actually working */
|
||||
data = ast_read32(ast, 0xf004);
|
||||
if (data != 0xFFFFFFFF) {
|
||||
/* P2A works, grab silicon revision */
|
||||
ast->config_mode = ast_use_p2a;
|
||||
|
||||
DRM_INFO("Using P2A bridge for configuration\n");
|
||||
|
||||
/* Read SCU7c (silicon revision register) */
|
||||
ast_write32(ast, 0xf004, 0x1e6e0000);
|
||||
ast_write32(ast, 0xf000, 0x1);
|
||||
*scu_rev = ast_read32(ast, 0x1207c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* We have a P2A bridge but it's disabled */
|
||||
DRM_INFO("P2A bridge disabled, using default configuration\n");
|
||||
}
|
||||
|
||||
static int ast_detect_chip(struct drm_device *dev, bool *need_post)
|
||||
{
|
||||
struct ast_private *ast = dev->dev_private;
|
||||
uint32_t data, jreg;
|
||||
uint32_t jreg, scu_rev;
|
||||
|
||||
/*
|
||||
* If VGA isn't enabled, we need to enable now or subsequent
|
||||
* access to the scratch registers will fail. We also inform
|
||||
* our caller that it needs to POST the chip
|
||||
* (Assumption: VGA not enabled -> need to POST)
|
||||
*/
|
||||
if (!ast_is_vga_enabled(dev)) {
|
||||
ast_enable_vga(dev);
|
||||
DRM_INFO("VGA not enabled on entry, requesting chip POST\n");
|
||||
*need_post = true;
|
||||
} else
|
||||
*need_post = false;
|
||||
|
||||
|
||||
/* Enable extended register access */
|
||||
ast_enable_mmio(dev);
|
||||
ast_open_key(ast);
|
||||
|
||||
/* Find out whether P2A works or whether to use device-tree */
|
||||
ast_detect_config_mode(dev, &scu_rev);
|
||||
|
||||
/* Identify chipset */
|
||||
if (dev->pdev->device == PCI_CHIP_AST1180) {
|
||||
ast->chip = AST1100;
|
||||
DRM_INFO("AST 1180 detected\n");
|
||||
} else {
|
||||
if (dev->pdev->revision >= 0x30) {
|
||||
if (dev->pdev->revision >= 0x40) {
|
||||
ast->chip = AST2500;
|
||||
DRM_INFO("AST 2500 detected\n");
|
||||
} else if (dev->pdev->revision >= 0x30) {
|
||||
ast->chip = AST2400;
|
||||
DRM_INFO("AST 2400 detected\n");
|
||||
} else if (dev->pdev->revision >= 0x20) {
|
||||
ast->chip = AST2300;
|
||||
DRM_INFO("AST 2300 detected\n");
|
||||
} else if (dev->pdev->revision >= 0x10) {
|
||||
uint32_t data;
|
||||
ast_write32(ast, 0xf004, 0x1e6e0000);
|
||||
ast_write32(ast, 0xf000, 0x1);
|
||||
|
||||
data = ast_read32(ast, 0x1207c);
|
||||
switch (data & 0x0300) {
|
||||
switch (scu_rev & 0x0300) {
|
||||
case 0x0200:
|
||||
ast->chip = AST1100;
|
||||
DRM_INFO("AST 1100 detected\n");
|
||||
|
@ -110,26 +177,6 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If VGA isn't enabled, we need to enable now or subsequent
|
||||
* access to the scratch registers will fail. We also inform
|
||||
* our caller that it needs to POST the chip
|
||||
* (Assumption: VGA not enabled -> need to POST)
|
||||
*/
|
||||
if (!ast_is_vga_enabled(dev)) {
|
||||
ast_enable_vga(dev);
|
||||
ast_enable_mmio(dev);
|
||||
DRM_INFO("VGA not enabled on entry, requesting chip POST\n");
|
||||
*need_post = true;
|
||||
} else
|
||||
*need_post = false;
|
||||
|
||||
/* Check P2A Access */
|
||||
ast->DisableP2A = true;
|
||||
data = ast_read32(ast, 0xf004);
|
||||
if (data != 0xFFFFFFFF)
|
||||
ast->DisableP2A = false;
|
||||
|
||||
/* Check if we support wide screen */
|
||||
switch (ast->chip) {
|
||||
case AST1180:
|
||||
|
@ -146,17 +193,15 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
|
|||
ast->support_wide_screen = true;
|
||||
else {
|
||||
ast->support_wide_screen = false;
|
||||
if (ast->DisableP2A == false) {
|
||||
/* Read SCU7c (silicon revision register) */
|
||||
ast_write32(ast, 0xf004, 0x1e6e0000);
|
||||
ast_write32(ast, 0xf000, 0x1);
|
||||
data = ast_read32(ast, 0x1207c);
|
||||
data &= 0x300;
|
||||
if (ast->chip == AST2300 && data == 0x0) /* ast1300 */
|
||||
ast->support_wide_screen = true;
|
||||
if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
|
||||
ast->support_wide_screen = true;
|
||||
}
|
||||
if (ast->chip == AST2300 &&
|
||||
(scu_rev & 0x300) == 0x0) /* ast1300 */
|
||||
ast->support_wide_screen = true;
|
||||
if (ast->chip == AST2400 &&
|
||||
(scu_rev & 0x300) == 0x100) /* ast1400 */
|
||||
ast->support_wide_screen = true;
|
||||
if (ast->chip == AST2500 &&
|
||||
scu_rev == 0x100) /* ast2510 */
|
||||
ast->support_wide_screen = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -220,85 +265,121 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
|
|||
|
||||
static int ast_get_dram_info(struct drm_device *dev)
|
||||
{
|
||||
struct device_node *np = dev->pdev->dev.of_node;
|
||||
struct ast_private *ast = dev->dev_private;
|
||||
uint32_t data, data2;
|
||||
uint32_t denum, num, div, ref_pll;
|
||||
uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap;
|
||||
uint32_t denum, num, div, ref_pll, dsel;
|
||||
|
||||
if (ast->DisableP2A)
|
||||
{
|
||||
ast->dram_bus_width = 16;
|
||||
ast->dram_type = AST_DRAM_1Gx16;
|
||||
ast->mclk = 396;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ast->config_mode) {
|
||||
case ast_use_dt:
|
||||
/*
|
||||
* If some properties are missing, use reasonable
|
||||
* defaults for AST2400
|
||||
*/
|
||||
if (of_property_read_u32(np, "aspeed,mcr-configuration",
|
||||
&mcr_cfg))
|
||||
mcr_cfg = 0x00000577;
|
||||
if (of_property_read_u32(np, "aspeed,mcr-scu-mpll",
|
||||
&mcr_scu_mpll))
|
||||
mcr_scu_mpll = 0x000050C0;
|
||||
if (of_property_read_u32(np, "aspeed,mcr-scu-strap",
|
||||
&mcr_scu_strap))
|
||||
mcr_scu_strap = 0;
|
||||
break;
|
||||
case ast_use_p2a:
|
||||
ast_write32(ast, 0xf004, 0x1e6e0000);
|
||||
ast_write32(ast, 0xf000, 0x1);
|
||||
data = ast_read32(ast, 0x10004);
|
||||
|
||||
if (data & 0x40)
|
||||
ast->dram_bus_width = 16;
|
||||
mcr_cfg = ast_read32(ast, 0x10004);
|
||||
mcr_scu_mpll = ast_read32(ast, 0x10120);
|
||||
mcr_scu_strap = ast_read32(ast, 0x10170);
|
||||
break;
|
||||
case ast_use_defaults:
|
||||
default:
|
||||
ast->dram_bus_width = 16;
|
||||
ast->dram_type = AST_DRAM_1Gx16;
|
||||
if (ast->chip == AST2500)
|
||||
ast->mclk = 800;
|
||||
else
|
||||
ast->dram_bus_width = 32;
|
||||
ast->mclk = 396;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ast->chip == AST2300 || ast->chip == AST2400) {
|
||||
switch (data & 0x03) {
|
||||
case 0:
|
||||
ast->dram_type = AST_DRAM_512Mx16;
|
||||
break;
|
||||
default:
|
||||
case 1:
|
||||
ast->dram_type = AST_DRAM_1Gx16;
|
||||
break;
|
||||
case 2:
|
||||
ast->dram_type = AST_DRAM_2Gx16;
|
||||
break;
|
||||
case 3:
|
||||
ast->dram_type = AST_DRAM_4Gx16;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (data & 0x0c) {
|
||||
case 0:
|
||||
case 4:
|
||||
ast->dram_type = AST_DRAM_512Mx16;
|
||||
break;
|
||||
case 8:
|
||||
if (data & 0x40)
|
||||
ast->dram_type = AST_DRAM_1Gx16;
|
||||
else
|
||||
ast->dram_type = AST_DRAM_512Mx32;
|
||||
break;
|
||||
case 0xc:
|
||||
ast->dram_type = AST_DRAM_1Gx32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mcr_cfg & 0x40)
|
||||
ast->dram_bus_width = 16;
|
||||
else
|
||||
ast->dram_bus_width = 32;
|
||||
|
||||
data = ast_read32(ast, 0x10120);
|
||||
data2 = ast_read32(ast, 0x10170);
|
||||
if (data2 & 0x2000)
|
||||
ref_pll = 14318;
|
||||
else
|
||||
ref_pll = 12000;
|
||||
|
||||
denum = data & 0x1f;
|
||||
num = (data & 0x3fe0) >> 5;
|
||||
data = (data & 0xc000) >> 14;
|
||||
switch (data) {
|
||||
case 3:
|
||||
div = 0x4;
|
||||
break;
|
||||
case 2:
|
||||
case 1:
|
||||
div = 0x2;
|
||||
if (ast->chip == AST2500) {
|
||||
switch (mcr_cfg & 0x03) {
|
||||
case 0:
|
||||
ast->dram_type = AST_DRAM_1Gx16;
|
||||
break;
|
||||
default:
|
||||
div = 0x1;
|
||||
case 1:
|
||||
ast->dram_type = AST_DRAM_2Gx16;
|
||||
break;
|
||||
case 2:
|
||||
ast->dram_type = AST_DRAM_4Gx16;
|
||||
break;
|
||||
case 3:
|
||||
ast->dram_type = AST_DRAM_8Gx16;
|
||||
break;
|
||||
}
|
||||
} else if (ast->chip == AST2300 || ast->chip == AST2400) {
|
||||
switch (mcr_cfg & 0x03) {
|
||||
case 0:
|
||||
ast->dram_type = AST_DRAM_512Mx16;
|
||||
break;
|
||||
default:
|
||||
case 1:
|
||||
ast->dram_type = AST_DRAM_1Gx16;
|
||||
break;
|
||||
case 2:
|
||||
ast->dram_type = AST_DRAM_2Gx16;
|
||||
break;
|
||||
case 3:
|
||||
ast->dram_type = AST_DRAM_4Gx16;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (mcr_cfg & 0x0c) {
|
||||
case 0:
|
||||
case 4:
|
||||
ast->dram_type = AST_DRAM_512Mx16;
|
||||
break;
|
||||
case 8:
|
||||
if (mcr_cfg & 0x40)
|
||||
ast->dram_type = AST_DRAM_1Gx16;
|
||||
else
|
||||
ast->dram_type = AST_DRAM_512Mx32;
|
||||
break;
|
||||
case 0xc:
|
||||
ast->dram_type = AST_DRAM_1Gx32;
|
||||
break;
|
||||
}
|
||||
ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
|
||||
}
|
||||
|
||||
if (mcr_scu_strap & 0x2000)
|
||||
ref_pll = 14318;
|
||||
else
|
||||
ref_pll = 12000;
|
||||
|
||||
denum = mcr_scu_mpll & 0x1f;
|
||||
num = (mcr_scu_mpll & 0x3fe0) >> 5;
|
||||
dsel = (mcr_scu_mpll & 0xc000) >> 14;
|
||||
switch (dsel) {
|
||||
case 3:
|
||||
div = 0x4;
|
||||
break;
|
||||
case 2:
|
||||
case 1:
|
||||
div = 0x2;
|
||||
break;
|
||||
default:
|
||||
div = 0x1;
|
||||
break;
|
||||
}
|
||||
ast->mclk = ref_pll * (num + 2) / ((denum + 2) * (div * 1000));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -437,17 +518,19 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
|
||||
ast_detect_chip(dev, &need_post);
|
||||
|
||||
if (need_post)
|
||||
ast_post_gpu(dev);
|
||||
|
||||
if (ast->chip != AST1180) {
|
||||
ret = ast_get_dram_info(dev);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
ast->vram_size = ast_get_vram_info(dev);
|
||||
DRM_INFO("dram %d %d %d %08x\n", ast->mclk, ast->dram_type, ast->dram_bus_width, ast->vram_size);
|
||||
DRM_INFO("dram MCLK=%u Mhz type=%d bus_width=%d size=%08x\n",
|
||||
ast->mclk, ast->dram_type,
|
||||
ast->dram_bus_width, ast->vram_size);
|
||||
}
|
||||
|
||||
if (need_post)
|
||||
ast_post_gpu(dev);
|
||||
|
||||
ret = ast_mm_init(ast);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
|
@ -465,6 +548,7 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
ast->chip == AST2200 ||
|
||||
ast->chip == AST2300 ||
|
||||
ast->chip == AST2400 ||
|
||||
ast->chip == AST2500 ||
|
||||
ast->chip == AST1180) {
|
||||
dev->mode_config.max_width = 1920;
|
||||
dev->mode_config.max_height = 2048;
|
||||
|
|
|
@ -81,9 +81,9 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
|
|||
struct ast_private *ast = crtc->dev->dev_private;
|
||||
const struct drm_framebuffer *fb = crtc->primary->fb;
|
||||
u32 refresh_rate_index = 0, mode_id, color_index, refresh_rate;
|
||||
const struct ast_vbios_enhtable *best = NULL;
|
||||
u32 hborder, vborder;
|
||||
bool check_sync;
|
||||
struct ast_vbios_enhtable *best = NULL;
|
||||
|
||||
switch (fb->format->cpp[0] * 8) {
|
||||
case 8:
|
||||
|
@ -147,7 +147,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
|
|||
refresh_rate = drm_mode_vrefresh(mode);
|
||||
check_sync = vbios_mode->enh_table->flags & WideScreenMode;
|
||||
do {
|
||||
struct ast_vbios_enhtable *loop = vbios_mode->enh_table;
|
||||
const struct ast_vbios_enhtable *loop = vbios_mode->enh_table;
|
||||
|
||||
while (loop->refresh_rate != 0xff) {
|
||||
if ((check_sync) &&
|
||||
|
@ -227,7 +227,7 @@ static void ast_set_std_reg(struct drm_crtc *crtc, struct drm_display_mode *mode
|
|||
struct ast_vbios_mode_info *vbios_mode)
|
||||
{
|
||||
struct ast_private *ast = crtc->dev->dev_private;
|
||||
struct ast_vbios_stdtable *stdtable;
|
||||
const struct ast_vbios_stdtable *stdtable;
|
||||
u32 i;
|
||||
u8 jreg;
|
||||
|
||||
|
@ -273,7 +273,11 @@ static void ast_set_crtc_reg(struct drm_crtc *crtc, struct drm_display_mode *mod
|
|||
{
|
||||
struct ast_private *ast = crtc->dev->dev_private;
|
||||
u8 jreg05 = 0, jreg07 = 0, jreg09 = 0, jregAC = 0, jregAD = 0, jregAE = 0;
|
||||
u16 temp;
|
||||
u16 temp, precache = 0;
|
||||
|
||||
if ((ast->chip == AST2500) &&
|
||||
(vbios_mode->enh_table->flags & AST2500PreCatchCRT))
|
||||
precache = 40;
|
||||
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00);
|
||||
|
||||
|
@ -299,12 +303,12 @@ static void ast_set_crtc_reg(struct drm_crtc *crtc, struct drm_display_mode *mod
|
|||
jregAD |= 0x01; /* HBE D[5] */
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x03, 0xE0, (temp & 0x1f));
|
||||
|
||||
temp = (mode->crtc_hsync_start >> 3) - 1;
|
||||
temp = ((mode->crtc_hsync_start-precache) >> 3) - 1;
|
||||
if (temp & 0x100)
|
||||
jregAC |= 0x40; /* HRS D[5] */
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x04, 0x00, temp);
|
||||
|
||||
temp = ((mode->crtc_hsync_end >> 3) - 1) & 0x3f;
|
||||
temp = (((mode->crtc_hsync_end-precache) >> 3) - 1) & 0x3f;
|
||||
if (temp & 0x20)
|
||||
jregAD |= 0x04; /* HRE D[5] */
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x05, 0x60, (u8)((temp & 0x1f) | jreg05));
|
||||
|
@ -365,6 +369,11 @@ static void ast_set_crtc_reg(struct drm_crtc *crtc, struct drm_display_mode *mod
|
|||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x09, 0xdf, jreg09);
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAE, 0x00, (jregAE | 0x80));
|
||||
|
||||
if (precache)
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x80);
|
||||
else
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x00);
|
||||
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x80);
|
||||
}
|
||||
|
||||
|
@ -384,14 +393,18 @@ static void ast_set_dclk_reg(struct drm_device *dev, struct drm_display_mode *mo
|
|||
struct ast_vbios_mode_info *vbios_mode)
|
||||
{
|
||||
struct ast_private *ast = dev->dev_private;
|
||||
struct ast_vbios_dclk_info *clk_info;
|
||||
const struct ast_vbios_dclk_info *clk_info;
|
||||
|
||||
clk_info = &dclk_table[vbios_mode->enh_table->dclk_index];
|
||||
if (ast->chip == AST2500)
|
||||
clk_info = &dclk_table_ast2500[vbios_mode->enh_table->dclk_index];
|
||||
else
|
||||
clk_info = &dclk_table[vbios_mode->enh_table->dclk_index];
|
||||
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc0, 0x00, clk_info->param1);
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc1, 0x00, clk_info->param2);
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xbb, 0x0f,
|
||||
(clk_info->param3 & 0x80) | ((clk_info->param3 & 0x3) << 4));
|
||||
(clk_info->param3 & 0xc0) |
|
||||
((clk_info->param3 & 0x3) << 4));
|
||||
}
|
||||
|
||||
static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
|
@ -425,7 +438,8 @@ static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode
|
|||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8);
|
||||
|
||||
/* Set Threshold */
|
||||
if (ast->chip == AST2300 || ast->chip == AST2400) {
|
||||
if (ast->chip == AST2300 || ast->chip == AST2400 ||
|
||||
ast->chip == AST2500) {
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x78);
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x60);
|
||||
} else if (ast->chip == AST2100 ||
|
||||
|
@ -800,7 +814,9 @@ static int ast_mode_valid(struct drm_connector *connector,
|
|||
if ((mode->hdisplay == 1600) && (mode->vdisplay == 900))
|
||||
return MODE_OK;
|
||||
|
||||
if ((ast->chip == AST2100) || (ast->chip == AST2200) || (ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip == AST1180)) {
|
||||
if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
|
||||
(ast->chip == AST2300) || (ast->chip == AST2400) ||
|
||||
(ast->chip == AST2500) || (ast->chip == AST1180)) {
|
||||
if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
|
||||
return MODE_OK;
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
|
||||
#include "ast_dram_tables.h"
|
||||
|
||||
static void ast_init_dram_2300(struct drm_device *dev);
|
||||
static void ast_post_chip_2300(struct drm_device *dev);
|
||||
static void ast_post_chip_2500(struct drm_device *dev);
|
||||
|
||||
void ast_enable_vga(struct drm_device *dev)
|
||||
{
|
||||
|
@ -58,13 +59,9 @@ bool ast_is_vga_enabled(struct drm_device *dev)
|
|||
/* TODO 1180 */
|
||||
} else {
|
||||
ch = ast_io_read8(ast, AST_IO_VGA_ENABLE_PORT);
|
||||
if (ch) {
|
||||
ast_open_key(ast);
|
||||
ch = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff);
|
||||
return ch & 0x04;
|
||||
}
|
||||
return !!(ch & 0x01);
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static const u8 extreginfo[] = { 0x0f, 0x04, 0x1c, 0xff };
|
||||
|
@ -79,10 +76,11 @@ ast_set_def_ext_reg(struct drm_device *dev)
|
|||
const u8 *ext_reg_info;
|
||||
|
||||
/* reset scratch */
|
||||
for (i = 0x81; i <= 0x8f; i++)
|
||||
for (i = 0x81; i <= 0x9f; i++)
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, 0x00);
|
||||
|
||||
if (ast->chip == AST2300 || ast->chip == AST2400) {
|
||||
if (ast->chip == AST2300 || ast->chip == AST2400 ||
|
||||
ast->chip == AST2500) {
|
||||
if (dev->pdev->revision >= 0x20)
|
||||
ext_reg_info = extreginfo_ast2300;
|
||||
else
|
||||
|
@ -106,7 +104,8 @@ ast_set_def_ext_reg(struct drm_device *dev)
|
|||
|
||||
/* Enable RAMDAC for A1 */
|
||||
reg = 0x04;
|
||||
if (ast->chip == AST2300 || ast->chip == AST2400)
|
||||
if (ast->chip == AST2300 || ast->chip == AST2400 ||
|
||||
ast->chip == AST2500)
|
||||
reg |= 0x20;
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg);
|
||||
}
|
||||
|
@ -375,21 +374,20 @@ void ast_post_gpu(struct drm_device *dev)
|
|||
pci_write_config_dword(ast->dev->pdev, 0x04, reg);
|
||||
|
||||
ast_enable_vga(dev);
|
||||
ast_enable_mmio(dev);
|
||||
ast_open_key(ast);
|
||||
ast_enable_mmio(dev);
|
||||
ast_set_def_ext_reg(dev);
|
||||
|
||||
if (ast->DisableP2A == false)
|
||||
{
|
||||
if (ast->chip == AST2300 || ast->chip == AST2400)
|
||||
ast_init_dram_2300(dev);
|
||||
if (ast->config_mode == ast_use_p2a) {
|
||||
if (ast->chip == AST2500)
|
||||
ast_post_chip_2500(dev);
|
||||
else if (ast->chip == AST2300 || ast->chip == AST2400)
|
||||
ast_post_chip_2300(dev);
|
||||
else
|
||||
ast_init_dram_reg(dev);
|
||||
|
||||
ast_init_3rdtx(dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (ast->tx_chip_type != AST_TX_NONE)
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80); /* Enable DVO */
|
||||
}
|
||||
|
@ -448,87 +446,72 @@ static const u32 pattern[8] = {
|
|||
0x7C61D253
|
||||
};
|
||||
|
||||
static int mmc_test_burst(struct ast_private *ast, u32 datagen)
|
||||
static bool mmc_test(struct ast_private *ast, u32 datagen, u8 test_ctl)
|
||||
{
|
||||
u32 data, timeout;
|
||||
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x000000c1 | (datagen << 3));
|
||||
timeout = 0;
|
||||
do {
|
||||
data = ast_mindwm(ast, 0x1e6e0070) & 0x3000;
|
||||
if (data & 0x2000) {
|
||||
return 0;
|
||||
}
|
||||
if (++timeout > TIMEOUT) {
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
|
||||
return 0;
|
||||
}
|
||||
} while (!data);
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mmc_test_burst2(struct ast_private *ast, u32 datagen)
|
||||
{
|
||||
u32 data, timeout;
|
||||
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x00000041 | (datagen << 3));
|
||||
timeout = 0;
|
||||
do {
|
||||
data = ast_mindwm(ast, 0x1e6e0070) & 0x1000;
|
||||
if (++timeout > TIMEOUT) {
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x0);
|
||||
return -1;
|
||||
}
|
||||
} while (!data);
|
||||
data = ast_mindwm(ast, 0x1e6e0078);
|
||||
data = (data | (data >> 16)) & 0xffff;
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x0);
|
||||
return data;
|
||||
}
|
||||
|
||||
static int mmc_test_single(struct ast_private *ast, u32 datagen)
|
||||
{
|
||||
u32 data, timeout;
|
||||
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x000000c5 | (datagen << 3));
|
||||
ast_moutdwm(ast, 0x1e6e0070, (datagen << 3) | test_ctl);
|
||||
timeout = 0;
|
||||
do {
|
||||
data = ast_mindwm(ast, 0x1e6e0070) & 0x3000;
|
||||
if (data & 0x2000)
|
||||
return 0;
|
||||
return false;
|
||||
if (++timeout > TIMEOUT) {
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x0);
|
||||
return 0;
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
|
||||
return false;
|
||||
}
|
||||
} while (!data);
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x0);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int mmc_test_single2(struct ast_private *ast, u32 datagen)
|
||||
static u32 mmc_test2(struct ast_private *ast, u32 datagen, u8 test_ctl)
|
||||
{
|
||||
u32 data, timeout;
|
||||
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x00000005 | (datagen << 3));
|
||||
ast_moutdwm(ast, 0x1e6e0070, (datagen << 3) | test_ctl);
|
||||
timeout = 0;
|
||||
do {
|
||||
data = ast_mindwm(ast, 0x1e6e0070) & 0x1000;
|
||||
if (++timeout > TIMEOUT) {
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x0);
|
||||
return -1;
|
||||
return 0xffffffff;
|
||||
}
|
||||
} while (!data);
|
||||
data = ast_mindwm(ast, 0x1e6e0078);
|
||||
data = (data | (data >> 16)) & 0xffff;
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x0);
|
||||
ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
static bool mmc_test_burst(struct ast_private *ast, u32 datagen)
|
||||
{
|
||||
return mmc_test(ast, datagen, 0xc1);
|
||||
}
|
||||
|
||||
static u32 mmc_test_burst2(struct ast_private *ast, u32 datagen)
|
||||
{
|
||||
return mmc_test2(ast, datagen, 0x41);
|
||||
}
|
||||
|
||||
static bool mmc_test_single(struct ast_private *ast, u32 datagen)
|
||||
{
|
||||
return mmc_test(ast, datagen, 0xc5);
|
||||
}
|
||||
|
||||
static u32 mmc_test_single2(struct ast_private *ast, u32 datagen)
|
||||
{
|
||||
return mmc_test2(ast, datagen, 0x05);
|
||||
}
|
||||
|
||||
static bool mmc_test_single_2500(struct ast_private *ast, u32 datagen)
|
||||
{
|
||||
return mmc_test(ast, datagen, 0x85);
|
||||
}
|
||||
|
||||
static int cbr_test(struct ast_private *ast)
|
||||
{
|
||||
u32 data;
|
||||
|
@ -604,16 +587,16 @@ static u32 cbr_scan2(struct ast_private *ast)
|
|||
return data2;
|
||||
}
|
||||
|
||||
static u32 cbr_test3(struct ast_private *ast)
|
||||
static bool cbr_test3(struct ast_private *ast)
|
||||
{
|
||||
if (!mmc_test_burst(ast, 0))
|
||||
return 0;
|
||||
return false;
|
||||
if (!mmc_test_single(ast, 0))
|
||||
return 0;
|
||||
return 1;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static u32 cbr_scan3(struct ast_private *ast)
|
||||
static bool cbr_scan3(struct ast_private *ast)
|
||||
{
|
||||
u32 patcnt, loop;
|
||||
|
||||
|
@ -624,9 +607,9 @@ static u32 cbr_scan3(struct ast_private *ast)
|
|||
break;
|
||||
}
|
||||
if (loop == 2)
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool finetuneDQI_L(struct ast_private *ast, struct ast2300_dram_param *param)
|
||||
|
@ -1612,7 +1595,7 @@ static void ddr2_init(struct ast_private *ast, struct ast2300_dram_param *param)
|
|||
|
||||
}
|
||||
|
||||
static void ast_init_dram_2300(struct drm_device *dev)
|
||||
static void ast_post_chip_2300(struct drm_device *dev)
|
||||
{
|
||||
struct ast_private *ast = dev->dev_private;
|
||||
struct ast2300_dram_param param;
|
||||
|
@ -1638,12 +1621,44 @@ static void ast_init_dram_2300(struct drm_device *dev)
|
|||
temp |= 0x73;
|
||||
ast_write32(ast, 0x12008, temp);
|
||||
|
||||
param.dram_freq = 396;
|
||||
param.dram_type = AST_DDR3;
|
||||
temp = ast_mindwm(ast, 0x1e6e2070);
|
||||
if (temp & 0x01000000)
|
||||
param.dram_type = AST_DDR2;
|
||||
param.dram_chipid = ast->dram_type;
|
||||
param.dram_freq = ast->mclk;
|
||||
param.vram_size = ast->vram_size;
|
||||
switch (temp & 0x18000000) {
|
||||
case 0:
|
||||
param.dram_chipid = AST_DRAM_512Mx16;
|
||||
break;
|
||||
default:
|
||||
case 0x08000000:
|
||||
param.dram_chipid = AST_DRAM_1Gx16;
|
||||
break;
|
||||
case 0x10000000:
|
||||
param.dram_chipid = AST_DRAM_2Gx16;
|
||||
break;
|
||||
case 0x18000000:
|
||||
param.dram_chipid = AST_DRAM_4Gx16;
|
||||
break;
|
||||
}
|
||||
switch (temp & 0x0c) {
|
||||
default:
|
||||
case 0x00:
|
||||
param.vram_size = AST_VIDMEM_SIZE_8M;
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
param.vram_size = AST_VIDMEM_SIZE_16M;
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
param.vram_size = AST_VIDMEM_SIZE_32M;
|
||||
break;
|
||||
|
||||
case 0x0c:
|
||||
param.vram_size = AST_VIDMEM_SIZE_64M;
|
||||
break;
|
||||
}
|
||||
|
||||
if (param.dram_type == AST_DDR3) {
|
||||
get_ddr3_info(ast, ¶m);
|
||||
|
@ -1663,3 +1678,404 @@ static void ast_init_dram_2300(struct drm_device *dev)
|
|||
} while ((reg & 0x40) == 0);
|
||||
}
|
||||
|
||||
static bool cbr_test_2500(struct ast_private *ast)
|
||||
{
|
||||
ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);
|
||||
ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);
|
||||
if (!mmc_test_burst(ast, 0))
|
||||
return false;
|
||||
if (!mmc_test_single_2500(ast, 0))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ddr_test_2500(struct ast_private *ast)
|
||||
{
|
||||
ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);
|
||||
ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);
|
||||
if (!mmc_test_burst(ast, 0))
|
||||
return false;
|
||||
if (!mmc_test_burst(ast, 1))
|
||||
return false;
|
||||
if (!mmc_test_burst(ast, 2))
|
||||
return false;
|
||||
if (!mmc_test_burst(ast, 3))
|
||||
return false;
|
||||
if (!mmc_test_single_2500(ast, 0))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ddr_init_common_2500(struct ast_private *ast)
|
||||
{
|
||||
ast_moutdwm(ast, 0x1E6E0034, 0x00020080);
|
||||
ast_moutdwm(ast, 0x1E6E0008, 0x2003000F);
|
||||
ast_moutdwm(ast, 0x1E6E0038, 0x00000FFF);
|
||||
ast_moutdwm(ast, 0x1E6E0040, 0x88448844);
|
||||
ast_moutdwm(ast, 0x1E6E0044, 0x24422288);
|
||||
ast_moutdwm(ast, 0x1E6E0048, 0x22222222);
|
||||
ast_moutdwm(ast, 0x1E6E004C, 0x22222222);
|
||||
ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
|
||||
ast_moutdwm(ast, 0x1E6E0208, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1E6E0218, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1E6E0220, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1E6E0228, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1E6E0230, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1E6E02A8, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1E6E02B0, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1E6E0240, 0x86000000);
|
||||
ast_moutdwm(ast, 0x1E6E0244, 0x00008600);
|
||||
ast_moutdwm(ast, 0x1E6E0248, 0x80000000);
|
||||
ast_moutdwm(ast, 0x1E6E024C, 0x80808080);
|
||||
}
|
||||
|
||||
static void ddr_phy_init_2500(struct ast_private *ast)
|
||||
{
|
||||
u32 data, pass, timecnt;
|
||||
|
||||
pass = 0;
|
||||
ast_moutdwm(ast, 0x1E6E0060, 0x00000005);
|
||||
while (!pass) {
|
||||
for (timecnt = 0; timecnt < TIMEOUT; timecnt++) {
|
||||
data = ast_mindwm(ast, 0x1E6E0060) & 0x1;
|
||||
if (!data)
|
||||
break;
|
||||
}
|
||||
if (timecnt != TIMEOUT) {
|
||||
data = ast_mindwm(ast, 0x1E6E0300) & 0x000A0000;
|
||||
if (!data)
|
||||
pass = 1;
|
||||
}
|
||||
if (!pass) {
|
||||
ast_moutdwm(ast, 0x1E6E0060, 0x00000000);
|
||||
udelay(10); /* delay 10 us */
|
||||
ast_moutdwm(ast, 0x1E6E0060, 0x00000005);
|
||||
}
|
||||
}
|
||||
|
||||
ast_moutdwm(ast, 0x1E6E0060, 0x00000006);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check DRAM Size
|
||||
* 1Gb : 0x80000000 ~ 0x87FFFFFF
|
||||
* 2Gb : 0x80000000 ~ 0x8FFFFFFF
|
||||
* 4Gb : 0x80000000 ~ 0x9FFFFFFF
|
||||
* 8Gb : 0x80000000 ~ 0xBFFFFFFF
|
||||
*/
|
||||
static void check_dram_size_2500(struct ast_private *ast, u32 tRFC)
|
||||
{
|
||||
u32 reg_04, reg_14;
|
||||
|
||||
reg_04 = ast_mindwm(ast, 0x1E6E0004) & 0xfffffffc;
|
||||
reg_14 = ast_mindwm(ast, 0x1E6E0014) & 0xffffff00;
|
||||
|
||||
ast_moutdwm(ast, 0xA0100000, 0x41424344);
|
||||
ast_moutdwm(ast, 0x90100000, 0x35363738);
|
||||
ast_moutdwm(ast, 0x88100000, 0x292A2B2C);
|
||||
ast_moutdwm(ast, 0x80100000, 0x1D1E1F10);
|
||||
|
||||
/* Check 8Gbit */
|
||||
if (ast_mindwm(ast, 0xA0100000) == 0x41424344) {
|
||||
reg_04 |= 0x03;
|
||||
reg_14 |= (tRFC >> 24) & 0xFF;
|
||||
/* Check 4Gbit */
|
||||
} else if (ast_mindwm(ast, 0x90100000) == 0x35363738) {
|
||||
reg_04 |= 0x02;
|
||||
reg_14 |= (tRFC >> 16) & 0xFF;
|
||||
/* Check 2Gbit */
|
||||
} else if (ast_mindwm(ast, 0x88100000) == 0x292A2B2C) {
|
||||
reg_04 |= 0x01;
|
||||
reg_14 |= (tRFC >> 8) & 0xFF;
|
||||
} else {
|
||||
reg_14 |= tRFC & 0xFF;
|
||||
}
|
||||
ast_moutdwm(ast, 0x1E6E0004, reg_04);
|
||||
ast_moutdwm(ast, 0x1E6E0014, reg_14);
|
||||
}
|
||||
|
||||
static void enable_cache_2500(struct ast_private *ast)
|
||||
{
|
||||
u32 reg_04, data;
|
||||
|
||||
reg_04 = ast_mindwm(ast, 0x1E6E0004);
|
||||
ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x1000);
|
||||
|
||||
do
|
||||
data = ast_mindwm(ast, 0x1E6E0004);
|
||||
while (!(data & 0x80000));
|
||||
ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x400);
|
||||
}
|
||||
|
||||
static void set_mpll_2500(struct ast_private *ast)
|
||||
{
|
||||
u32 addr, data, param;
|
||||
|
||||
/* Reset MMC */
|
||||
ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
|
||||
ast_moutdwm(ast, 0x1E6E0034, 0x00020080);
|
||||
for (addr = 0x1e6e0004; addr < 0x1e6e0090;) {
|
||||
ast_moutdwm(ast, addr, 0x0);
|
||||
addr += 4;
|
||||
}
|
||||
ast_moutdwm(ast, 0x1E6E0034, 0x00020000);
|
||||
|
||||
ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
|
||||
data = ast_mindwm(ast, 0x1E6E2070) & 0x00800000;
|
||||
if (data) {
|
||||
/* CLKIN = 25MHz */
|
||||
param = 0x930023E0;
|
||||
ast_moutdwm(ast, 0x1E6E2160, 0x00011320);
|
||||
} else {
|
||||
/* CLKIN = 24MHz */
|
||||
param = 0x93002400;
|
||||
}
|
||||
ast_moutdwm(ast, 0x1E6E2020, param);
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
static void reset_mmc_2500(struct ast_private *ast)
|
||||
{
|
||||
ast_moutdwm(ast, 0x1E78505C, 0x00000004);
|
||||
ast_moutdwm(ast, 0x1E785044, 0x00000001);
|
||||
ast_moutdwm(ast, 0x1E785048, 0x00004755);
|
||||
ast_moutdwm(ast, 0x1E78504C, 0x00000013);
|
||||
mdelay(100);
|
||||
ast_moutdwm(ast, 0x1E785054, 0x00000077);
|
||||
ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
|
||||
}
|
||||
|
||||
static void ddr3_init_2500(struct ast_private *ast, const u32 *ddr_table)
|
||||
{
|
||||
|
||||
ast_moutdwm(ast, 0x1E6E0004, 0x00000303);
|
||||
ast_moutdwm(ast, 0x1E6E0010, ddr_table[REGIDX_010]);
|
||||
ast_moutdwm(ast, 0x1E6E0014, ddr_table[REGIDX_014]);
|
||||
ast_moutdwm(ast, 0x1E6E0018, ddr_table[REGIDX_018]);
|
||||
ast_moutdwm(ast, 0x1E6E0020, ddr_table[REGIDX_020]); /* MODEREG4/6 */
|
||||
ast_moutdwm(ast, 0x1E6E0024, ddr_table[REGIDX_024]); /* MODEREG5 */
|
||||
ast_moutdwm(ast, 0x1E6E002C, ddr_table[REGIDX_02C] | 0x100); /* MODEREG0/2 */
|
||||
ast_moutdwm(ast, 0x1E6E0030, ddr_table[REGIDX_030]); /* MODEREG1/3 */
|
||||
|
||||
/* DDR PHY Setting */
|
||||
ast_moutdwm(ast, 0x1E6E0200, 0x02492AAE);
|
||||
ast_moutdwm(ast, 0x1E6E0204, 0x00001001);
|
||||
ast_moutdwm(ast, 0x1E6E020C, 0x55E00B0B);
|
||||
ast_moutdwm(ast, 0x1E6E0210, 0x20000000);
|
||||
ast_moutdwm(ast, 0x1E6E0214, ddr_table[REGIDX_214]);
|
||||
ast_moutdwm(ast, 0x1E6E02E0, ddr_table[REGIDX_2E0]);
|
||||
ast_moutdwm(ast, 0x1E6E02E4, ddr_table[REGIDX_2E4]);
|
||||
ast_moutdwm(ast, 0x1E6E02E8, ddr_table[REGIDX_2E8]);
|
||||
ast_moutdwm(ast, 0x1E6E02EC, ddr_table[REGIDX_2EC]);
|
||||
ast_moutdwm(ast, 0x1E6E02F0, ddr_table[REGIDX_2F0]);
|
||||
ast_moutdwm(ast, 0x1E6E02F4, ddr_table[REGIDX_2F4]);
|
||||
ast_moutdwm(ast, 0x1E6E02F8, ddr_table[REGIDX_2F8]);
|
||||
ast_moutdwm(ast, 0x1E6E0290, 0x00100008);
|
||||
ast_moutdwm(ast, 0x1E6E02C0, 0x00000006);
|
||||
|
||||
/* Controller Setting */
|
||||
ast_moutdwm(ast, 0x1E6E0034, 0x00020091);
|
||||
|
||||
/* Wait DDR PHY init done */
|
||||
ddr_phy_init_2500(ast);
|
||||
|
||||
ast_moutdwm(ast, 0x1E6E0120, ddr_table[REGIDX_PLL]);
|
||||
ast_moutdwm(ast, 0x1E6E000C, 0x42AA5C81);
|
||||
ast_moutdwm(ast, 0x1E6E0034, 0x0001AF93);
|
||||
|
||||
check_dram_size_2500(ast, ddr_table[REGIDX_RFC]);
|
||||
enable_cache_2500(ast);
|
||||
ast_moutdwm(ast, 0x1E6E001C, 0x00000008);
|
||||
ast_moutdwm(ast, 0x1E6E0038, 0xFFFFFF00);
|
||||
}
|
||||
|
||||
static void ddr4_init_2500(struct ast_private *ast, const u32 *ddr_table)
|
||||
{
|
||||
u32 data, data2, pass, retrycnt;
|
||||
u32 ddr_vref, phy_vref;
|
||||
u32 min_ddr_vref = 0, min_phy_vref = 0;
|
||||
u32 max_ddr_vref = 0, max_phy_vref = 0;
|
||||
|
||||
ast_moutdwm(ast, 0x1E6E0004, 0x00000313);
|
||||
ast_moutdwm(ast, 0x1E6E0010, ddr_table[REGIDX_010]);
|
||||
ast_moutdwm(ast, 0x1E6E0014, ddr_table[REGIDX_014]);
|
||||
ast_moutdwm(ast, 0x1E6E0018, ddr_table[REGIDX_018]);
|
||||
ast_moutdwm(ast, 0x1E6E0020, ddr_table[REGIDX_020]); /* MODEREG4/6 */
|
||||
ast_moutdwm(ast, 0x1E6E0024, ddr_table[REGIDX_024]); /* MODEREG5 */
|
||||
ast_moutdwm(ast, 0x1E6E002C, ddr_table[REGIDX_02C] | 0x100); /* MODEREG0/2 */
|
||||
ast_moutdwm(ast, 0x1E6E0030, ddr_table[REGIDX_030]); /* MODEREG1/3 */
|
||||
|
||||
/* DDR PHY Setting */
|
||||
ast_moutdwm(ast, 0x1E6E0200, 0x42492AAE);
|
||||
ast_moutdwm(ast, 0x1E6E0204, 0x09002000);
|
||||
ast_moutdwm(ast, 0x1E6E020C, 0x55E00B0B);
|
||||
ast_moutdwm(ast, 0x1E6E0210, 0x20000000);
|
||||
ast_moutdwm(ast, 0x1E6E0214, ddr_table[REGIDX_214]);
|
||||
ast_moutdwm(ast, 0x1E6E02E0, ddr_table[REGIDX_2E0]);
|
||||
ast_moutdwm(ast, 0x1E6E02E4, ddr_table[REGIDX_2E4]);
|
||||
ast_moutdwm(ast, 0x1E6E02E8, ddr_table[REGIDX_2E8]);
|
||||
ast_moutdwm(ast, 0x1E6E02EC, ddr_table[REGIDX_2EC]);
|
||||
ast_moutdwm(ast, 0x1E6E02F0, ddr_table[REGIDX_2F0]);
|
||||
ast_moutdwm(ast, 0x1E6E02F4, ddr_table[REGIDX_2F4]);
|
||||
ast_moutdwm(ast, 0x1E6E02F8, ddr_table[REGIDX_2F8]);
|
||||
ast_moutdwm(ast, 0x1E6E0290, 0x00100008);
|
||||
ast_moutdwm(ast, 0x1E6E02C4, 0x3C183C3C);
|
||||
ast_moutdwm(ast, 0x1E6E02C8, 0x00631E0E);
|
||||
|
||||
/* Controller Setting */
|
||||
ast_moutdwm(ast, 0x1E6E0034, 0x0001A991);
|
||||
|
||||
/* Train PHY Vref first */
|
||||
pass = 0;
|
||||
|
||||
for (retrycnt = 0; retrycnt < 4 && pass == 0; retrycnt++) {
|
||||
max_phy_vref = 0x0;
|
||||
pass = 0;
|
||||
ast_moutdwm(ast, 0x1E6E02C0, 0x00001C06);
|
||||
for (phy_vref = 0x40; phy_vref < 0x80; phy_vref++) {
|
||||
ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1E6E0060, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1E6E02CC, phy_vref | (phy_vref << 8));
|
||||
/* Fire DFI Init */
|
||||
ddr_phy_init_2500(ast);
|
||||
ast_moutdwm(ast, 0x1E6E000C, 0x00005C01);
|
||||
if (cbr_test_2500(ast)) {
|
||||
pass++;
|
||||
data = ast_mindwm(ast, 0x1E6E03D0);
|
||||
data2 = data >> 8;
|
||||
data = data & 0xff;
|
||||
if (data > data2)
|
||||
data = data2;
|
||||
if (max_phy_vref < data) {
|
||||
max_phy_vref = data;
|
||||
min_phy_vref = phy_vref;
|
||||
}
|
||||
} else if (pass > 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
ast_moutdwm(ast, 0x1E6E02CC, min_phy_vref | (min_phy_vref << 8));
|
||||
|
||||
/* Train DDR Vref next */
|
||||
pass = 0;
|
||||
|
||||
for (retrycnt = 0; retrycnt < 4 && pass == 0; retrycnt++) {
|
||||
min_ddr_vref = 0xFF;
|
||||
max_ddr_vref = 0x0;
|
||||
pass = 0;
|
||||
for (ddr_vref = 0x00; ddr_vref < 0x40; ddr_vref++) {
|
||||
ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1E6E0060, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1E6E02C0, 0x00000006 | (ddr_vref << 8));
|
||||
/* Fire DFI Init */
|
||||
ddr_phy_init_2500(ast);
|
||||
ast_moutdwm(ast, 0x1E6E000C, 0x00005C01);
|
||||
if (cbr_test_2500(ast)) {
|
||||
pass++;
|
||||
if (min_ddr_vref > ddr_vref)
|
||||
min_ddr_vref = ddr_vref;
|
||||
if (max_ddr_vref < ddr_vref)
|
||||
max_ddr_vref = ddr_vref;
|
||||
} else if (pass != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1E6E0060, 0x00000000);
|
||||
ddr_vref = (min_ddr_vref + max_ddr_vref + 1) >> 1;
|
||||
ast_moutdwm(ast, 0x1E6E02C0, 0x00000006 | (ddr_vref << 8));
|
||||
|
||||
/* Wait DDR PHY init done */
|
||||
ddr_phy_init_2500(ast);
|
||||
|
||||
ast_moutdwm(ast, 0x1E6E0120, ddr_table[REGIDX_PLL]);
|
||||
ast_moutdwm(ast, 0x1E6E000C, 0x42AA5C81);
|
||||
ast_moutdwm(ast, 0x1E6E0034, 0x0001AF93);
|
||||
|
||||
check_dram_size_2500(ast, ddr_table[REGIDX_RFC]);
|
||||
enable_cache_2500(ast);
|
||||
ast_moutdwm(ast, 0x1E6E001C, 0x00000008);
|
||||
ast_moutdwm(ast, 0x1E6E0038, 0xFFFFFF00);
|
||||
}
|
||||
|
||||
static bool ast_dram_init_2500(struct ast_private *ast)
|
||||
{
|
||||
u32 data;
|
||||
u32 max_tries = 5;
|
||||
|
||||
do {
|
||||
if (max_tries-- == 0)
|
||||
return false;
|
||||
set_mpll_2500(ast);
|
||||
reset_mmc_2500(ast);
|
||||
ddr_init_common_2500(ast);
|
||||
|
||||
data = ast_mindwm(ast, 0x1E6E2070);
|
||||
if (data & 0x01000000)
|
||||
ddr4_init_2500(ast, ast2500_ddr4_1600_timing_table);
|
||||
else
|
||||
ddr3_init_2500(ast, ast2500_ddr3_1600_timing_table);
|
||||
} while (!ddr_test_2500(ast));
|
||||
|
||||
ast_moutdwm(ast, 0x1E6E2040, ast_mindwm(ast, 0x1E6E2040) | 0x41);
|
||||
|
||||
/* Patch code */
|
||||
data = ast_mindwm(ast, 0x1E6E200C) & 0xF9FFFFFF;
|
||||
ast_moutdwm(ast, 0x1E6E200C, data | 0x10000000);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ast_post_chip_2500(struct drm_device *dev)
|
||||
{
|
||||
struct ast_private *ast = dev->dev_private;
|
||||
u32 temp;
|
||||
u8 reg;
|
||||
|
||||
reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
|
||||
if ((reg & 0x80) == 0) {/* vga only */
|
||||
/* Clear bus lock condition */
|
||||
ast_moutdwm(ast, 0x1e600000, 0xAEED1A03);
|
||||
ast_moutdwm(ast, 0x1e600084, 0x00010000);
|
||||
ast_moutdwm(ast, 0x1e600088, 0x00000000);
|
||||
ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
|
||||
ast_write32(ast, 0xf004, 0x1e6e0000);
|
||||
ast_write32(ast, 0xf000, 0x1);
|
||||
ast_write32(ast, 0x12000, 0x1688a8a8);
|
||||
while (ast_read32(ast, 0x12000) != 0x1)
|
||||
;
|
||||
|
||||
ast_write32(ast, 0x10000, 0xfc600309);
|
||||
while (ast_read32(ast, 0x10000) != 0x1)
|
||||
;
|
||||
|
||||
/* Slow down CPU/AHB CLK in VGA only mode */
|
||||
temp = ast_read32(ast, 0x12008);
|
||||
temp |= 0x73;
|
||||
ast_write32(ast, 0x12008, temp);
|
||||
|
||||
/* Reset USB port to patch USB unknown device issue */
|
||||
ast_moutdwm(ast, 0x1e6e2090, 0x20000000);
|
||||
temp = ast_mindwm(ast, 0x1e6e2094);
|
||||
temp |= 0x00004000;
|
||||
ast_moutdwm(ast, 0x1e6e2094, temp);
|
||||
temp = ast_mindwm(ast, 0x1e6e2070);
|
||||
if (temp & 0x00800000) {
|
||||
ast_moutdwm(ast, 0x1e6e207c, 0x00800000);
|
||||
mdelay(100);
|
||||
ast_moutdwm(ast, 0x1e6e2070, 0x00800000);
|
||||
}
|
||||
|
||||
if (!ast_dram_init_2500(ast))
|
||||
DRM_ERROR("DRAM init failed !\n");
|
||||
|
||||
temp = ast_mindwm(ast, 0x1e6e2040);
|
||||
ast_moutdwm(ast, 0x1e6e2040, temp | 0x40);
|
||||
}
|
||||
|
||||
/* wait ready */
|
||||
do {
|
||||
reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
|
||||
} while ((reg & 0x40) == 0);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#define SyncPN (PVSync | NHSync)
|
||||
#define SyncNP (NVSync | PHSync)
|
||||
#define SyncNN (NVSync | NHSync)
|
||||
#define AST2500PreCatchCRT 0x00004000
|
||||
|
||||
/* DCLK Index */
|
||||
#define VCLK25_175 0x00
|
||||
|
@ -78,37 +79,67 @@
|
|||
#define VCLK97_75 0x19
|
||||
#define VCLK118_25 0x1A
|
||||
|
||||
static struct ast_vbios_dclk_info dclk_table[] = {
|
||||
{0x2C, 0xE7, 0x03}, /* 00: VCLK25_175 */
|
||||
{0x95, 0x62, 0x03}, /* 01: VCLK28_322 */
|
||||
{0x67, 0x63, 0x01}, /* 02: VCLK31_5 */
|
||||
{0x76, 0x63, 0x01}, /* 03: VCLK36 */
|
||||
{0xEE, 0x67, 0x01}, /* 04: VCLK40 */
|
||||
{0x82, 0x62, 0x01}, /* 05: VCLK49_5 */
|
||||
{0xC6, 0x64, 0x01}, /* 06: VCLK50 */
|
||||
{0x94, 0x62, 0x01}, /* 07: VCLK56_25 */
|
||||
{0x80, 0x64, 0x00}, /* 08: VCLK65 */
|
||||
{0x7B, 0x63, 0x00}, /* 09: VCLK75 */
|
||||
{0x67, 0x62, 0x00}, /* 0A: VCLK78_75 */
|
||||
{0x7C, 0x62, 0x00}, /* 0B: VCLK94_5 */
|
||||
{0x8E, 0x62, 0x00}, /* 0C: VCLK108 */
|
||||
{0x85, 0x24, 0x00}, /* 0D: VCLK135 */
|
||||
{0x67, 0x22, 0x00}, /* 0E: VCLK157_5 */
|
||||
{0x6A, 0x22, 0x00}, /* 0F: VCLK162 */
|
||||
{0x4d, 0x4c, 0x80}, /* 10: VCLK154 */
|
||||
{0xa7, 0x78, 0x80}, /* 11: VCLK83.5 */
|
||||
{0x28, 0x49, 0x80}, /* 12: VCLK106.5 */
|
||||
{0x37, 0x49, 0x80}, /* 13: VCLK146.25 */
|
||||
{0x1f, 0x45, 0x80}, /* 14: VCLK148.5 */
|
||||
{0x47, 0x6c, 0x80}, /* 15: VCLK71 */
|
||||
{0x25, 0x65, 0x80}, /* 16: VCLK88.75 */
|
||||
{0x77, 0x58, 0x80}, /* 17: VCLK119 */
|
||||
{0x32, 0x67, 0x80}, /* 18: VCLK85_5 */
|
||||
{0x6a, 0x6d, 0x80}, /* 19: VCLK97_75 */
|
||||
{0x3b, 0x2c, 0x81}, /* 1A: VCLK118_25 */
|
||||
static const struct ast_vbios_dclk_info dclk_table[] = {
|
||||
{0x2C, 0xE7, 0x03}, /* 00: VCLK25_175 */
|
||||
{0x95, 0x62, 0x03}, /* 01: VCLK28_322 */
|
||||
{0x67, 0x63, 0x01}, /* 02: VCLK31_5 */
|
||||
{0x76, 0x63, 0x01}, /* 03: VCLK36 */
|
||||
{0xEE, 0x67, 0x01}, /* 04: VCLK40 */
|
||||
{0x82, 0x62, 0x01}, /* 05: VCLK49_5 */
|
||||
{0xC6, 0x64, 0x01}, /* 06: VCLK50 */
|
||||
{0x94, 0x62, 0x01}, /* 07: VCLK56_25 */
|
||||
{0x80, 0x64, 0x00}, /* 08: VCLK65 */
|
||||
{0x7B, 0x63, 0x00}, /* 09: VCLK75 */
|
||||
{0x67, 0x62, 0x00}, /* 0A: VCLK78_75 */
|
||||
{0x7C, 0x62, 0x00}, /* 0B: VCLK94_5 */
|
||||
{0x8E, 0x62, 0x00}, /* 0C: VCLK108 */
|
||||
{0x85, 0x24, 0x00}, /* 0D: VCLK135 */
|
||||
{0x67, 0x22, 0x00}, /* 0E: VCLK157_5 */
|
||||
{0x6A, 0x22, 0x00}, /* 0F: VCLK162 */
|
||||
{0x4d, 0x4c, 0x80}, /* 10: VCLK154 */
|
||||
{0xa7, 0x78, 0x80}, /* 11: VCLK83.5 */
|
||||
{0x28, 0x49, 0x80}, /* 12: VCLK106.5 */
|
||||
{0x37, 0x49, 0x80}, /* 13: VCLK146.25 */
|
||||
{0x1f, 0x45, 0x80}, /* 14: VCLK148.5 */
|
||||
{0x47, 0x6c, 0x80}, /* 15: VCLK71 */
|
||||
{0x25, 0x65, 0x80}, /* 16: VCLK88.75 */
|
||||
{0x77, 0x58, 0x80}, /* 17: VCLK119 */
|
||||
{0x32, 0x67, 0x80}, /* 18: VCLK85_5 */
|
||||
{0x6a, 0x6d, 0x80}, /* 19: VCLK97_75 */
|
||||
{0x3b, 0x2c, 0x81}, /* 1A: VCLK118_25 */
|
||||
};
|
||||
|
||||
static struct ast_vbios_stdtable vbios_stdtable[] = {
|
||||
static const struct ast_vbios_dclk_info dclk_table_ast2500[] = {
|
||||
{0x2C, 0xE7, 0x03}, /* 00: VCLK25_175 */
|
||||
{0x95, 0x62, 0x03}, /* 01: VCLK28_322 */
|
||||
{0x67, 0x63, 0x01}, /* 02: VCLK31_5 */
|
||||
{0x76, 0x63, 0x01}, /* 03: VCLK36 */
|
||||
{0xEE, 0x67, 0x01}, /* 04: VCLK40 */
|
||||
{0x82, 0x62, 0x01}, /* 05: VCLK49_5 */
|
||||
{0xC6, 0x64, 0x01}, /* 06: VCLK50 */
|
||||
{0x94, 0x62, 0x01}, /* 07: VCLK56_25 */
|
||||
{0x80, 0x64, 0x00}, /* 08: VCLK65 */
|
||||
{0x7B, 0x63, 0x00}, /* 09: VCLK75 */
|
||||
{0x67, 0x62, 0x00}, /* 0A: VCLK78_75 */
|
||||
{0x7C, 0x62, 0x00}, /* 0B: VCLK94_5 */
|
||||
{0x8E, 0x62, 0x00}, /* 0C: VCLK108 */
|
||||
{0x85, 0x24, 0x00}, /* 0D: VCLK135 */
|
||||
{0x67, 0x22, 0x00}, /* 0E: VCLK157_5 */
|
||||
{0x6A, 0x22, 0x00}, /* 0F: VCLK162 */
|
||||
{0x4d, 0x4c, 0x80}, /* 10: VCLK154 */
|
||||
{0xa7, 0x78, 0x80}, /* 11: VCLK83.5 */
|
||||
{0x28, 0x49, 0x80}, /* 12: VCLK106.5 */
|
||||
{0x37, 0x49, 0x80}, /* 13: VCLK146.25 */
|
||||
{0x1f, 0x45, 0x80}, /* 14: VCLK148.5 */
|
||||
{0x47, 0x6c, 0x80}, /* 15: VCLK71 */
|
||||
{0x25, 0x65, 0x80}, /* 16: VCLK88.75 */
|
||||
{0x58, 0x01, 0x42}, /* 17: VCLK119 */
|
||||
{0x32, 0x67, 0x80}, /* 18: VCLK85_5 */
|
||||
{0x6a, 0x6d, 0x80}, /* 19: VCLK97_75 */
|
||||
{0x44, 0x20, 0x43}, /* 1A: VCLK118_25 */
|
||||
};
|
||||
|
||||
static const struct ast_vbios_stdtable vbios_stdtable[] = {
|
||||
/* MD_2_3_400 */
|
||||
{
|
||||
0x67,
|
||||
|
@ -181,21 +212,21 @@ static struct ast_vbios_stdtable vbios_stdtable[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct ast_vbios_enhtable res_640x480[] = {
|
||||
static const struct ast_vbios_enhtable res_640x480[] = {
|
||||
{ 800, 640, 8, 96, 525, 480, 2, 2, VCLK25_175, /* 60Hz */
|
||||
(SyncNN | HBorder | VBorder | Charx8Dot), 60, 1, 0x2E },
|
||||
{ 832, 640, 16, 40, 520, 480, 1, 3, VCLK31_5, /* 72Hz */
|
||||
(SyncNN | HBorder | VBorder | Charx8Dot), 72, 2, 0x2E },
|
||||
{ 840, 640, 16, 64, 500, 480, 1, 3, VCLK31_5, /* 75Hz */
|
||||
(SyncNN | Charx8Dot) , 75, 3, 0x2E },
|
||||
{ 832, 640, 56, 56, 509, 480, 1, 3, VCLK36, /* 85Hz */
|
||||
{ 832, 640, 56, 56, 509, 480, 1, 3, VCLK36, /* 85Hz */
|
||||
(SyncNN | Charx8Dot) , 85, 4, 0x2E },
|
||||
{ 832, 640, 56, 56, 509, 480, 1, 3, VCLK36, /* end */
|
||||
{ 832, 640, 56, 56, 509, 480, 1, 3, VCLK36, /* end */
|
||||
(SyncNN | Charx8Dot) , 0xFF, 4, 0x2E },
|
||||
};
|
||||
|
||||
static struct ast_vbios_enhtable res_800x600[] = {
|
||||
{1024, 800, 24, 72, 625, 600, 1, 2, VCLK36, /* 56Hz */
|
||||
static const struct ast_vbios_enhtable res_800x600[] = {
|
||||
{1024, 800, 24, 72, 625, 600, 1, 2, VCLK36, /* 56Hz */
|
||||
(SyncPP | Charx8Dot), 56, 1, 0x30 },
|
||||
{1056, 800, 40, 128, 628, 600, 1, 4, VCLK40, /* 60Hz */
|
||||
(SyncPP | Charx8Dot), 60, 2, 0x30 },
|
||||
|
@ -210,7 +241,7 @@ static struct ast_vbios_enhtable res_800x600[] = {
|
|||
};
|
||||
|
||||
|
||||
static struct ast_vbios_enhtable res_1024x768[] = {
|
||||
static const struct ast_vbios_enhtable res_1024x768[] = {
|
||||
{1344, 1024, 24, 136, 806, 768, 3, 6, VCLK65, /* 60Hz */
|
||||
(SyncNN | Charx8Dot), 60, 1, 0x31 },
|
||||
{1328, 1024, 24, 136, 806, 768, 3, 6, VCLK75, /* 70Hz */
|
||||
|
@ -223,7 +254,7 @@ static struct ast_vbios_enhtable res_1024x768[] = {
|
|||
(SyncPP | Charx8Dot), 0xFF, 4, 0x31 },
|
||||
};
|
||||
|
||||
static struct ast_vbios_enhtable res_1280x1024[] = {
|
||||
static const struct ast_vbios_enhtable res_1280x1024[] = {
|
||||
{1688, 1280, 48, 112, 1066, 1024, 1, 3, VCLK108, /* 60Hz */
|
||||
(SyncPP | Charx8Dot), 60, 1, 0x32 },
|
||||
{1688, 1280, 16, 144, 1066, 1024, 1, 3, VCLK135, /* 75Hz */
|
||||
|
@ -234,7 +265,7 @@ static struct ast_vbios_enhtable res_1280x1024[] = {
|
|||
(SyncPP | Charx8Dot), 0xFF, 3, 0x32 },
|
||||
};
|
||||
|
||||
static struct ast_vbios_enhtable res_1600x1200[] = {
|
||||
static const struct ast_vbios_enhtable res_1600x1200[] = {
|
||||
{2160, 1600, 64, 192, 1250, 1200, 1, 3, VCLK162, /* 60Hz */
|
||||
(SyncPP | Charx8Dot), 60, 1, 0x33 },
|
||||
{2160, 1600, 64, 192, 1250, 1200, 1, 3, VCLK162, /* end */
|
||||
|
@ -242,34 +273,39 @@ static struct ast_vbios_enhtable res_1600x1200[] = {
|
|||
};
|
||||
|
||||
/* 16:9 */
|
||||
static struct ast_vbios_enhtable res_1360x768[] = {
|
||||
{1792, 1360, 64,112, 795, 768, 3, 6, VCLK85_5, /* 60Hz */
|
||||
static const struct ast_vbios_enhtable res_1360x768[] = {
|
||||
{1792, 1360, 64, 112, 795, 768, 3, 6, VCLK85_5, /* 60Hz */
|
||||
(SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x39 },
|
||||
{1792, 1360, 64,112, 795, 768, 3, 6, VCLK85_5, /* end */
|
||||
(SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x39 },
|
||||
{1792, 1360, 64, 112, 795, 768, 3, 6, VCLK85_5, /* end */
|
||||
(SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
|
||||
AST2500PreCatchCRT), 0xFF, 1, 0x39 },
|
||||
};
|
||||
|
||||
static struct ast_vbios_enhtable res_1600x900[] = {
|
||||
{1760, 1600, 48, 32, 926, 900, 3, 5, VCLK97_75, /* 60Hz CVT RB */
|
||||
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x3A },
|
||||
{2112, 1600, 88,168, 934, 900, 3, 5, VCLK118_25, /* 60Hz CVT */
|
||||
static const struct ast_vbios_enhtable res_1600x900[] = {
|
||||
{1760, 1600, 48, 32, 926, 900, 3, 5, VCLK97_75, /* 60Hz CVT RB */
|
||||
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
|
||||
AST2500PreCatchCRT), 60, 1, 0x3A },
|
||||
{2112, 1600, 88, 168, 934, 900, 3, 5, VCLK118_25, /* 60Hz CVT */
|
||||
(SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x3A },
|
||||
{2112, 1600, 88,168, 934, 900, 3, 5, VCLK118_25, /* 60Hz CVT */
|
||||
{2112, 1600, 88, 168, 934, 900, 3, 5, VCLK118_25, /* 60Hz CVT */
|
||||
(SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 0x3A },
|
||||
};
|
||||
|
||||
static struct ast_vbios_enhtable res_1920x1080[] = {
|
||||
static const struct ast_vbios_enhtable res_1920x1080[] = {
|
||||
{2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5, /* 60Hz */
|
||||
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x38 },
|
||||
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
|
||||
AST2500PreCatchCRT), 60, 1, 0x38 },
|
||||
{2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5, /* 60Hz */
|
||||
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x38 },
|
||||
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
|
||||
AST2500PreCatchCRT), 0xFF, 1, 0x38 },
|
||||
};
|
||||
|
||||
|
||||
/* 16:10 */
|
||||
static struct ast_vbios_enhtable res_1280x800[] = {
|
||||
{1440, 1280, 48, 32, 823, 800, 3, 6, VCLK71, /* 60Hz RB */
|
||||
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x35 },
|
||||
static const struct ast_vbios_enhtable res_1280x800[] = {
|
||||
{1440, 1280, 48, 32, 823, 800, 3, 6, VCLK71, /* 60Hz RB */
|
||||
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
|
||||
AST2500PreCatchCRT), 60, 1, 0x35 },
|
||||
{1680, 1280, 72,128, 831, 800, 3, 6, VCLK83_5, /* 60Hz */
|
||||
(SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x35 },
|
||||
{1680, 1280, 72,128, 831, 800, 3, 6, VCLK83_5, /* 60Hz */
|
||||
|
@ -277,29 +313,33 @@ static struct ast_vbios_enhtable res_1280x800[] = {
|
|||
|
||||
};
|
||||
|
||||
static struct ast_vbios_enhtable res_1440x900[] = {
|
||||
static const struct ast_vbios_enhtable res_1440x900[] = {
|
||||
{1600, 1440, 48, 32, 926, 900, 3, 6, VCLK88_75, /* 60Hz RB */
|
||||
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x36 },
|
||||
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
|
||||
AST2500PreCatchCRT), 60, 1, 0x36 },
|
||||
{1904, 1440, 80,152, 934, 900, 3, 6, VCLK106_5, /* 60Hz */
|
||||
(SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x36 },
|
||||
{1904, 1440, 80,152, 934, 900, 3, 6, VCLK106_5, /* 60Hz */
|
||||
(SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 0x36 },
|
||||
};
|
||||
|
||||
static struct ast_vbios_enhtable res_1680x1050[] = {
|
||||
{1840, 1680, 48, 32, 1080, 1050, 3, 6, VCLK119, /* 60Hz RB */
|
||||
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x37 },
|
||||
static const struct ast_vbios_enhtable res_1680x1050[] = {
|
||||
{1840, 1680, 48, 32, 1080, 1050, 3, 6, VCLK119, /* 60Hz RB */
|
||||
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
|
||||
AST2500PreCatchCRT), 60, 1, 0x37 },
|
||||
{2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25, /* 60Hz */
|
||||
(SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x37 },
|
||||
{2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25, /* 60Hz */
|
||||
(SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 0x37 },
|
||||
};
|
||||
|
||||
static struct ast_vbios_enhtable res_1920x1200[] = {
|
||||
{2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB*/
|
||||
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x34 },
|
||||
{2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB */
|
||||
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x34 },
|
||||
static const struct ast_vbios_enhtable res_1920x1200[] = {
|
||||
{2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB*/
|
||||
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
|
||||
AST2500PreCatchCRT), 60, 1, 0x34 },
|
||||
{2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB */
|
||||
(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
|
||||
AST2500PreCatchCRT), 0xFF, 1, 0x34 },
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,7 @@ config ROCKCHIP_ANALOGIX_DP
|
|||
config ROCKCHIP_CDN_DP
|
||||
tristate "Rockchip cdn DP"
|
||||
depends on DRM_ROCKCHIP
|
||||
depends on EXTCON
|
||||
select SND_SOC_HDMI_CODEC if SND_SOC
|
||||
help
|
||||
This selects support for Rockchip SoC specific extensions
|
||||
|
|
|
@ -111,7 +111,7 @@ static int cdn_dp_clk_enable(struct cdn_dp_device *dp)
|
|||
ret = pm_runtime_get_sync(dp->dev);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(dp->dev, "cannot get pm runtime %d\n", ret);
|
||||
goto err_pclk;
|
||||
goto err_pm_runtime_get;
|
||||
}
|
||||
|
||||
reset_control_assert(dp->core_rst);
|
||||
|
@ -133,6 +133,8 @@ static int cdn_dp_clk_enable(struct cdn_dp_device *dp)
|
|||
return 0;
|
||||
|
||||
err_set_rate:
|
||||
pm_runtime_put(dp->dev);
|
||||
err_pm_runtime_get:
|
||||
clk_disable_unprepare(dp->core_clk);
|
||||
err_core_clk:
|
||||
clk_disable_unprepare(dp->pclk);
|
||||
|
|
|
@ -199,9 +199,14 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
|
|||
VMW_IOCTL_DEF(VMW_PRESENT_READBACK,
|
||||
vmw_present_readback_ioctl,
|
||||
DRM_MASTER | DRM_AUTH),
|
||||
/*
|
||||
* The permissions of the below ioctl are overridden in
|
||||
* vmw_generic_ioctl(). We require either
|
||||
* DRM_MASTER or capable(CAP_SYS_ADMIN).
|
||||
*/
|
||||
VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
|
||||
vmw_kms_update_layout_ioctl,
|
||||
DRM_MASTER | DRM_CONTROL_ALLOW),
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_CREATE_SHADER,
|
||||
vmw_shader_define_ioctl,
|
||||
DRM_AUTH | DRM_RENDER_ALLOW),
|
||||
|
@ -1123,6 +1128,10 @@ static long vmw_generic_ioctl(struct file *filp, unsigned int cmd,
|
|||
|
||||
return (long) vmw_execbuf_ioctl(dev, arg, file_priv,
|
||||
_IOC_SIZE(cmd));
|
||||
} else if (nr == DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT) {
|
||||
if (!drm_is_current_master(file_priv) &&
|
||||
!capable(CAP_SYS_ADMIN))
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if (unlikely(ioctl->cmd != cmd))
|
||||
|
|
|
@ -41,9 +41,9 @@
|
|||
#include <drm/ttm/ttm_module.h>
|
||||
#include "vmwgfx_fence.h"
|
||||
|
||||
#define VMWGFX_DRIVER_DATE "20160210"
|
||||
#define VMWGFX_DRIVER_DATE "20170221"
|
||||
#define VMWGFX_DRIVER_MAJOR 2
|
||||
#define VMWGFX_DRIVER_MINOR 11
|
||||
#define VMWGFX_DRIVER_MINOR 12
|
||||
#define VMWGFX_DRIVER_PATCHLEVEL 0
|
||||
#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
|
||||
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
|
||||
|
|
|
@ -159,7 +159,7 @@ static void zx_vl_rsz_setup(struct zx_plane *zplane, uint32_t format,
|
|||
void __iomem *rsz = zplane->rsz;
|
||||
u32 src_chroma_w = src_w;
|
||||
u32 src_chroma_h = src_h;
|
||||
u32 fmt;
|
||||
int fmt;
|
||||
|
||||
/* Set up source and destination resolution */
|
||||
zx_writel(rsz + RSZ_SRC_CFG, RSZ_VER(src_h - 1) | RSZ_HOR(src_w - 1));
|
||||
|
@ -203,7 +203,7 @@ static void zx_vl_plane_atomic_update(struct drm_plane *plane,
|
|||
u32 src_x, src_y, src_w, src_h;
|
||||
u32 dst_x, dst_y, dst_w, dst_h;
|
||||
uint32_t format;
|
||||
u32 fmt;
|
||||
int fmt;
|
||||
int num_planes;
|
||||
int i;
|
||||
|
||||
|
|
|
@ -258,9 +258,10 @@ static int rmi_f30_map_gpios(struct rmi_function *fn,
|
|||
|
||||
/*
|
||||
* Buttonpad could be also inferred from f30->has_mech_mouse_btns,
|
||||
* but I am not sure, so use only the pdata info.
|
||||
* but I am not sure, so use only the pdata info and the number of
|
||||
* mapped buttons.
|
||||
*/
|
||||
if (pdata->f30_data.buttonpad)
|
||||
if (pdata->f30_data.buttonpad || (button - BTN_LEFT == 1))
|
||||
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -29,7 +29,6 @@ struct led_pwm_data {
|
|||
unsigned int active_low;
|
||||
unsigned int period;
|
||||
int duty;
|
||||
bool can_sleep;
|
||||
};
|
||||
|
||||
struct led_pwm_priv {
|
||||
|
@ -49,8 +48,8 @@ static void __led_pwm_set(struct led_pwm_data *led_dat)
|
|||
pwm_enable(led_dat->pwm);
|
||||
}
|
||||
|
||||
static void led_pwm_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
static int led_pwm_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
struct led_pwm_data *led_dat =
|
||||
container_of(led_cdev, struct led_pwm_data, cdev);
|
||||
|
@ -66,12 +65,7 @@ static void led_pwm_set(struct led_classdev *led_cdev,
|
|||
led_dat->duty = duty;
|
||||
|
||||
__led_pwm_set(led_dat);
|
||||
}
|
||||
|
||||
static int led_pwm_set_blocking(struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
led_pwm_set(led_cdev, brightness);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -112,11 +106,7 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
|
|||
return ret;
|
||||
}
|
||||
|
||||
led_data->can_sleep = pwm_can_sleep(led_data->pwm);
|
||||
if (!led_data->can_sleep)
|
||||
led_data->cdev.brightness_set = led_pwm_set;
|
||||
else
|
||||
led_data->cdev.brightness_set_blocking = led_pwm_set_blocking;
|
||||
led_data->cdev.brightness_set_blocking = led_pwm_set;
|
||||
|
||||
/*
|
||||
* FIXME: pwm_apply_args() should be removed when switching to the
|
||||
|
|
|
@ -418,8 +418,9 @@ struct cxl_afu {
|
|||
struct dentry *debugfs;
|
||||
struct mutex contexts_lock;
|
||||
spinlock_t afu_cntl_lock;
|
||||
/* Used to block access to AFU config space while deconfigured */
|
||||
struct rw_semaphore configured_rwsem;
|
||||
|
||||
/* -1: AFU deconfigured/locked, >= 0: number of readers */
|
||||
atomic_t configured_state;
|
||||
|
||||
/* AFU error buffer fields and bin attribute for sysfs */
|
||||
u64 eb_len, eb_offset;
|
||||
|
|
|
@ -268,8 +268,7 @@ struct cxl_afu *cxl_alloc_afu(struct cxl *adapter, int slice)
|
|||
idr_init(&afu->contexts_idr);
|
||||
mutex_init(&afu->contexts_lock);
|
||||
spin_lock_init(&afu->afu_cntl_lock);
|
||||
init_rwsem(&afu->configured_rwsem);
|
||||
down_write(&afu->configured_rwsem);
|
||||
atomic_set(&afu->configured_state, -1);
|
||||
afu->prefault_mode = CXL_PREFAULT_NONE;
|
||||
afu->irqs_max = afu->adapter->user_irqs;
|
||||
|
||||
|
|
|
@ -1129,7 +1129,7 @@ static int pci_configure_afu(struct cxl_afu *afu, struct cxl *adapter, struct pc
|
|||
if ((rc = cxl_native_register_psl_irq(afu)))
|
||||
goto err2;
|
||||
|
||||
up_write(&afu->configured_rwsem);
|
||||
atomic_set(&afu->configured_state, 0);
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
|
@ -1142,7 +1142,14 @@ static int pci_configure_afu(struct cxl_afu *afu, struct cxl *adapter, struct pc
|
|||
|
||||
static void pci_deconfigure_afu(struct cxl_afu *afu)
|
||||
{
|
||||
down_write(&afu->configured_rwsem);
|
||||
/*
|
||||
* It's okay to deconfigure when AFU is already locked, otherwise wait
|
||||
* until there are no readers
|
||||
*/
|
||||
if (atomic_read(&afu->configured_state) != -1) {
|
||||
while (atomic_cmpxchg(&afu->configured_state, 0, -1) != -1)
|
||||
schedule();
|
||||
}
|
||||
cxl_native_release_psl_irq(afu);
|
||||
if (afu->adapter->native->sl_ops->release_serr_irq)
|
||||
afu->adapter->native->sl_ops->release_serr_irq(afu);
|
||||
|
|
|
@ -83,6 +83,16 @@ static inline struct cxl_afu *pci_bus_to_afu(struct pci_bus *bus)
|
|||
return phb ? phb->private_data : NULL;
|
||||
}
|
||||
|
||||
static void cxl_afu_configured_put(struct cxl_afu *afu)
|
||||
{
|
||||
atomic_dec_if_positive(&afu->configured_state);
|
||||
}
|
||||
|
||||
static bool cxl_afu_configured_get(struct cxl_afu *afu)
|
||||
{
|
||||
return atomic_inc_unless_negative(&afu->configured_state);
|
||||
}
|
||||
|
||||
static inline int cxl_pcie_config_info(struct pci_bus *bus, unsigned int devfn,
|
||||
struct cxl_afu *afu, int *_record)
|
||||
{
|
||||
|
@ -107,7 +117,7 @@ static int cxl_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
|
|||
|
||||
afu = pci_bus_to_afu(bus);
|
||||
/* Grab a reader lock on afu. */
|
||||
if (afu == NULL || !down_read_trylock(&afu->configured_rwsem))
|
||||
if (afu == NULL || !cxl_afu_configured_get(afu))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
rc = cxl_pcie_config_info(bus, devfn, afu, &record);
|
||||
|
@ -132,7 +142,7 @@ static int cxl_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
|
|||
}
|
||||
|
||||
out:
|
||||
up_read(&afu->configured_rwsem);
|
||||
cxl_afu_configured_put(afu);
|
||||
return rc ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
|
@ -144,7 +154,7 @@ static int cxl_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
|
|||
|
||||
afu = pci_bus_to_afu(bus);
|
||||
/* Grab a reader lock on afu. */
|
||||
if (afu == NULL || !down_read_trylock(&afu->configured_rwsem))
|
||||
if (afu == NULL || !cxl_afu_configured_get(afu))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
rc = cxl_pcie_config_info(bus, devfn, afu, &record);
|
||||
|
@ -166,7 +176,7 @@ static int cxl_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
|
|||
}
|
||||
|
||||
out:
|
||||
up_read(&afu->configured_rwsem);
|
||||
cxl_afu_configured_put(afu);
|
||||
return rc ? PCIBIOS_SET_FAILED : PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,9 +35,11 @@ static void pnv_php_register(struct device_node *dn);
|
|||
static void pnv_php_unregister_one(struct device_node *dn);
|
||||
static void pnv_php_unregister(struct device_node *dn);
|
||||
|
||||
static void pnv_php_disable_irq(struct pnv_php_slot *php_slot)
|
||||
static void pnv_php_disable_irq(struct pnv_php_slot *php_slot,
|
||||
bool disable_device)
|
||||
{
|
||||
struct pci_dev *pdev = php_slot->pdev;
|
||||
int irq = php_slot->irq;
|
||||
u16 ctrl;
|
||||
|
||||
if (php_slot->irq > 0) {
|
||||
|
@ -56,10 +58,14 @@ static void pnv_php_disable_irq(struct pnv_php_slot *php_slot)
|
|||
php_slot->wq = NULL;
|
||||
}
|
||||
|
||||
if (pdev->msix_enabled)
|
||||
pci_disable_msix(pdev);
|
||||
else if (pdev->msi_enabled)
|
||||
pci_disable_msi(pdev);
|
||||
if (disable_device || irq > 0) {
|
||||
if (pdev->msix_enabled)
|
||||
pci_disable_msix(pdev);
|
||||
else if (pdev->msi_enabled)
|
||||
pci_disable_msi(pdev);
|
||||
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
}
|
||||
|
||||
static void pnv_php_free_slot(struct kref *kref)
|
||||
|
@ -68,7 +74,7 @@ static void pnv_php_free_slot(struct kref *kref)
|
|||
struct pnv_php_slot, kref);
|
||||
|
||||
WARN_ON(!list_empty(&php_slot->children));
|
||||
pnv_php_disable_irq(php_slot);
|
||||
pnv_php_disable_irq(php_slot, false);
|
||||
kfree(php_slot->name);
|
||||
kfree(php_slot);
|
||||
}
|
||||
|
@ -76,7 +82,7 @@ static void pnv_php_free_slot(struct kref *kref)
|
|||
static inline void pnv_php_put_slot(struct pnv_php_slot *php_slot)
|
||||
{
|
||||
|
||||
if (WARN_ON(!php_slot))
|
||||
if (!php_slot)
|
||||
return;
|
||||
|
||||
kref_put(&php_slot->kref, pnv_php_free_slot);
|
||||
|
@ -430,9 +436,21 @@ static int pnv_php_enable(struct pnv_php_slot *php_slot, bool rescan)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Proceed if there have nothing behind the slot */
|
||||
if (presence == OPAL_PCI_SLOT_EMPTY)
|
||||
/*
|
||||
* Proceed if there have nothing behind the slot. However,
|
||||
* we should leave the slot in registered state at the
|
||||
* beginning. Otherwise, the PCI devices inserted afterwards
|
||||
* won't be probed and populated.
|
||||
*/
|
||||
if (presence == OPAL_PCI_SLOT_EMPTY) {
|
||||
if (!php_slot->power_state_check) {
|
||||
php_slot->power_state_check = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
goto scan;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the power supply to the slot is off, we can't detect
|
||||
|
@ -705,10 +723,15 @@ static irqreturn_t pnv_php_interrupt(int irq, void *data)
|
|||
if (sts & PCI_EXP_SLTSTA_DLLSC) {
|
||||
pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lsts);
|
||||
added = !!(lsts & PCI_EXP_LNKSTA_DLLLA);
|
||||
} else if (sts & PCI_EXP_SLTSTA_PDC) {
|
||||
} else if (!(php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC) &&
|
||||
(sts & PCI_EXP_SLTSTA_PDC)) {
|
||||
ret = pnv_pci_get_presence_state(php_slot->id, &presence);
|
||||
if (!ret)
|
||||
if (ret) {
|
||||
dev_warn(&pdev->dev, "PCI slot [%s] error %d getting presence (0x%04x), to retry the operation.\n",
|
||||
php_slot->name, ret, sts);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
added = !!(presence == OPAL_PCI_SLOT_PRESENT);
|
||||
} else {
|
||||
return IRQ_NONE;
|
||||
|
@ -752,6 +775,7 @@ static irqreturn_t pnv_php_interrupt(int irq, void *data)
|
|||
static void pnv_php_init_irq(struct pnv_php_slot *php_slot, int irq)
|
||||
{
|
||||
struct pci_dev *pdev = php_slot->pdev;
|
||||
u32 broken_pdc = 0;
|
||||
u16 sts, ctrl;
|
||||
int ret;
|
||||
|
||||
|
@ -759,29 +783,44 @@ static void pnv_php_init_irq(struct pnv_php_slot *php_slot, int irq)
|
|||
php_slot->wq = alloc_workqueue("pciehp-%s", 0, 0, php_slot->name);
|
||||
if (!php_slot->wq) {
|
||||
dev_warn(&pdev->dev, "Cannot alloc workqueue\n");
|
||||
pnv_php_disable_irq(php_slot);
|
||||
pnv_php_disable_irq(php_slot, true);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check PDC (Presence Detection Change) is broken or not */
|
||||
ret = of_property_read_u32(php_slot->dn, "ibm,slot-broken-pdc",
|
||||
&broken_pdc);
|
||||
if (!ret && broken_pdc)
|
||||
php_slot->flags |= PNV_PHP_FLAG_BROKEN_PDC;
|
||||
|
||||
/* Clear pending interrupts */
|
||||
pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &sts);
|
||||
sts |= (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC);
|
||||
if (php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC)
|
||||
sts |= PCI_EXP_SLTSTA_DLLSC;
|
||||
else
|
||||
sts |= (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC);
|
||||
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, sts);
|
||||
|
||||
/* Request the interrupt */
|
||||
ret = request_irq(irq, pnv_php_interrupt, IRQF_SHARED,
|
||||
php_slot->name, php_slot);
|
||||
if (ret) {
|
||||
pnv_php_disable_irq(php_slot);
|
||||
pnv_php_disable_irq(php_slot, true);
|
||||
dev_warn(&pdev->dev, "Error %d enabling IRQ %d\n", ret, irq);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable the interrupts */
|
||||
pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &ctrl);
|
||||
ctrl |= (PCI_EXP_SLTCTL_HPIE |
|
||||
PCI_EXP_SLTCTL_PDCE |
|
||||
PCI_EXP_SLTCTL_DLLSCE);
|
||||
if (php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC) {
|
||||
ctrl &= ~PCI_EXP_SLTCTL_PDCE;
|
||||
ctrl |= (PCI_EXP_SLTCTL_HPIE |
|
||||
PCI_EXP_SLTCTL_DLLSCE);
|
||||
} else {
|
||||
ctrl |= (PCI_EXP_SLTCTL_HPIE |
|
||||
PCI_EXP_SLTCTL_PDCE |
|
||||
PCI_EXP_SLTCTL_DLLSCE);
|
||||
}
|
||||
pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, ctrl);
|
||||
|
||||
/* The interrupt is initialized successfully when @irq is valid */
|
||||
|
@ -793,6 +832,14 @@ static void pnv_php_enable_irq(struct pnv_php_slot *php_slot)
|
|||
struct pci_dev *pdev = php_slot->pdev;
|
||||
int irq, ret;
|
||||
|
||||
/*
|
||||
* The MSI/MSIx interrupt might have been occupied by other
|
||||
* drivers. Don't populate the surprise hotplug capability
|
||||
* in that case.
|
||||
*/
|
||||
if (pci_dev_msi_enabled(pdev))
|
||||
return;
|
||||
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret) {
|
||||
dev_warn(&pdev->dev, "Error %d enabling device\n", ret);
|
||||
|
|
|
@ -76,7 +76,9 @@ config PWM_ATMEL_TCB
|
|||
|
||||
config PWM_BCM_IPROC
|
||||
tristate "iProc PWM support"
|
||||
depends on ARCH_BCM_IPROC
|
||||
depends on ARCH_BCM_IPROC || COMPILE_TEST
|
||||
depends on COMMON_CLK
|
||||
default ARCH_BCM_IPROC
|
||||
help
|
||||
Generic PWM framework driver for Broadcom iProc PWM block. This
|
||||
block is used in Broadcom iProc SoC's.
|
||||
|
|
|
@ -137,9 +137,14 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
|
|||
{
|
||||
struct pwm_device *pwm;
|
||||
|
||||
/* check, whether the driver supports a third cell for flags */
|
||||
if (pc->of_pwm_n_cells < 3)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* flags in the third cell are optional */
|
||||
if (args->args_count < 2)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (args->args[0] >= pc->npwm)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
|
@ -148,11 +153,10 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
|
|||
return pwm;
|
||||
|
||||
pwm->args.period = args->args[1];
|
||||
pwm->args.polarity = PWM_POLARITY_NORMAL;
|
||||
|
||||
if (args->args[2] & PWM_POLARITY_INVERTED)
|
||||
if (args->args_count > 2 && args->args[2] & PWM_POLARITY_INVERTED)
|
||||
pwm->args.polarity = PWM_POLARITY_INVERSED;
|
||||
else
|
||||
pwm->args.polarity = PWM_POLARITY_NORMAL;
|
||||
|
||||
return pwm;
|
||||
}
|
||||
|
@ -163,9 +167,14 @@ of_pwm_simple_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
|
|||
{
|
||||
struct pwm_device *pwm;
|
||||
|
||||
/* sanity check driver support */
|
||||
if (pc->of_pwm_n_cells < 2)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* all cells are required */
|
||||
if (args->args_count != pc->of_pwm_n_cells)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (args->args[0] >= pc->npwm)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
|
@ -663,24 +672,17 @@ struct pwm_device *of_pwm_get(struct device_node *np, const char *con_id)
|
|||
err = of_parse_phandle_with_args(np, "pwms", "#pwm-cells", index,
|
||||
&args);
|
||||
if (err) {
|
||||
pr_debug("%s(): can't parse \"pwms\" property\n", __func__);
|
||||
pr_err("%s(): can't parse \"pwms\" property\n", __func__);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
pc = of_node_to_pwmchip(args.np);
|
||||
if (IS_ERR(pc)) {
|
||||
pr_debug("%s(): PWM chip not found\n", __func__);
|
||||
pr_err("%s(): PWM chip not found\n", __func__);
|
||||
pwm = ERR_CAST(pc);
|
||||
goto put;
|
||||
}
|
||||
|
||||
if (args.args_count != pc->of_pwm_n_cells) {
|
||||
pr_debug("%s: wrong #pwm-cells for %s\n", np->full_name,
|
||||
args.np->full_name);
|
||||
pwm = ERR_PTR(-EINVAL);
|
||||
goto put;
|
||||
}
|
||||
|
||||
pwm = pc->of_xlate(pc, &args);
|
||||
if (IS_ERR(pwm))
|
||||
goto put;
|
||||
|
@ -757,12 +759,13 @@ void pwm_remove_table(struct pwm_lookup *table, size_t num)
|
|||
*/
|
||||
struct pwm_device *pwm_get(struct device *dev, const char *con_id)
|
||||
{
|
||||
struct pwm_device *pwm = ERR_PTR(-EPROBE_DEFER);
|
||||
const char *dev_id = dev ? dev_name(dev) : NULL;
|
||||
struct pwm_chip *chip = NULL;
|
||||
struct pwm_device *pwm;
|
||||
struct pwm_chip *chip;
|
||||
unsigned int best = 0;
|
||||
struct pwm_lookup *p, *chosen = NULL;
|
||||
unsigned int match;
|
||||
int err;
|
||||
|
||||
/* look up via DT first */
|
||||
if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node)
|
||||
|
@ -817,24 +820,35 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
|
|||
}
|
||||
}
|
||||
|
||||
if (!chosen) {
|
||||
pwm = ERR_PTR(-ENODEV);
|
||||
goto out;
|
||||
}
|
||||
mutex_unlock(&pwm_lookup_lock);
|
||||
|
||||
if (!chosen)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
chip = pwmchip_find_by_name(chosen->provider);
|
||||
|
||||
/*
|
||||
* If the lookup entry specifies a module, load the module and retry
|
||||
* the PWM chip lookup. This can be used to work around driver load
|
||||
* ordering issues if driver's can't be made to properly support the
|
||||
* deferred probe mechanism.
|
||||
*/
|
||||
if (!chip && chosen->module) {
|
||||
err = request_module(chosen->module);
|
||||
if (err == 0)
|
||||
chip = pwmchip_find_by_name(chosen->provider);
|
||||
}
|
||||
|
||||
if (!chip)
|
||||
goto out;
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
pwm = pwm_request_from_chip(chip, chosen->index, con_id ?: dev_id);
|
||||
if (IS_ERR(pwm))
|
||||
goto out;
|
||||
return pwm;
|
||||
|
||||
pwm->args.period = chosen->period;
|
||||
pwm->args.polarity = chosen->polarity;
|
||||
|
||||
out:
|
||||
mutex_unlock(&pwm_lookup_lock);
|
||||
return pwm;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pwm_get);
|
||||
|
@ -960,18 +974,6 @@ void devm_pwm_put(struct device *dev, struct pwm_device *pwm)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(devm_pwm_put);
|
||||
|
||||
/**
|
||||
* pwm_can_sleep() - report whether PWM access will sleep
|
||||
* @pwm: PWM device
|
||||
*
|
||||
* Returns: True if accessing the PWM can sleep, false otherwise.
|
||||
*/
|
||||
bool pwm_can_sleep(struct pwm_device *pwm)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pwm_can_sleep);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s)
|
||||
{
|
||||
|
|
|
@ -270,7 +270,6 @@ static int atmel_hlcdc_pwm_probe(struct platform_device *pdev)
|
|||
chip->chip.npwm = 1;
|
||||
chip->chip.of_xlate = of_pwm_xlate_with_flags;
|
||||
chip->chip.of_pwm_n_cells = 3;
|
||||
chip->chip.can_sleep = 1;
|
||||
|
||||
ret = pwmchip_add_with_polarity(&chip->chip, PWM_POLARITY_INVERSED);
|
||||
if (ret) {
|
||||
|
|
|
@ -385,7 +385,6 @@ static int atmel_pwm_probe(struct platform_device *pdev)
|
|||
|
||||
atmel_pwm->chip.base = -1;
|
||||
atmel_pwm->chip.npwm = 4;
|
||||
atmel_pwm->chip.can_sleep = true;
|
||||
atmel_pwm->config = data->config;
|
||||
atmel_pwm->updated_pwms = 0;
|
||||
mutex_init(&atmel_pwm->isr_lock);
|
||||
|
|
|
@ -276,7 +276,6 @@ static int kona_pwmc_probe(struct platform_device *pdev)
|
|||
kp->chip.npwm = 6;
|
||||
kp->chip.of_xlate = of_pwm_xlate_with_flags;
|
||||
kp->chip.of_pwm_n_cells = 3;
|
||||
kp->chip.can_sleep = true;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
kp->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
|
|
|
@ -206,7 +206,6 @@ static int berlin_pwm_probe(struct platform_device *pdev)
|
|||
pwm->chip.ops = &berlin_pwm_ops;
|
||||
pwm->chip.base = -1;
|
||||
pwm->chip.npwm = 4;
|
||||
pwm->chip.can_sleep = true;
|
||||
pwm->chip.of_xlate = of_pwm_xlate_with_flags;
|
||||
pwm->chip.of_pwm_n_cells = 3;
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ static void bfin_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
|||
disable_gptimer(priv->pin);
|
||||
}
|
||||
|
||||
static struct pwm_ops bfin_pwm_ops = {
|
||||
static const struct pwm_ops bfin_pwm_ops = {
|
||||
.request = bfin_pwm_request,
|
||||
.free = bfin_pwm_free,
|
||||
.config = bfin_pwm_config,
|
||||
|
|
|
@ -270,7 +270,6 @@ static int brcmstb_pwm_probe(struct platform_device *pdev)
|
|||
p->chip.ops = &brcmstb_pwm_ops;
|
||||
p->chip.base = -1;
|
||||
p->chip.npwm = 2;
|
||||
p->chip.can_sleep = true;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
p->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
|
|
|
@ -446,7 +446,6 @@ static int fsl_pwm_probe(struct platform_device *pdev)
|
|||
fpc->chip.of_pwm_n_cells = 3;
|
||||
fpc->chip.base = -1;
|
||||
fpc->chip.npwm = 8;
|
||||
fpc->chip.can_sleep = true;
|
||||
|
||||
ret = pwmchip_add(&fpc->chip);
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#define MX3_PWMCR_DOZEEN (1 << 24)
|
||||
#define MX3_PWMCR_WAITEN (1 << 23)
|
||||
#define MX3_PWMCR_DBGEN (1 << 22)
|
||||
#define MX3_PWMCR_POUTC (1 << 18)
|
||||
#define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16)
|
||||
#define MX3_PWMCR_CLKSRC_IPG (1 << 16)
|
||||
#define MX3_PWMCR_SWR (1 << 3)
|
||||
|
@ -49,15 +50,10 @@
|
|||
|
||||
struct imx_chip {
|
||||
struct clk *clk_per;
|
||||
struct clk *clk_ipg;
|
||||
|
||||
void __iomem *mmio_base;
|
||||
|
||||
struct pwm_chip chip;
|
||||
|
||||
int (*config)(struct pwm_chip *chip,
|
||||
struct pwm_device *pwm, int duty_ns, int period_ns);
|
||||
void (*set_enable)(struct pwm_chip *chip, bool enable);
|
||||
};
|
||||
|
||||
#define to_imx_chip(chip) container_of(chip, struct imx_chip, chip)
|
||||
|
@ -91,176 +87,170 @@ static int imx_pwm_config_v1(struct pwm_chip *chip,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void imx_pwm_set_enable_v1(struct pwm_chip *chip, bool enable)
|
||||
static int imx_pwm_enable_v1(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
{
|
||||
struct imx_chip *imx = to_imx_chip(chip);
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(imx->clk_per);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val = readl(imx->mmio_base + MX1_PWMC);
|
||||
val |= MX1_PWMC_EN;
|
||||
writel(val, imx->mmio_base + MX1_PWMC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void imx_pwm_disable_v1(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
{
|
||||
struct imx_chip *imx = to_imx_chip(chip);
|
||||
u32 val;
|
||||
|
||||
val = readl(imx->mmio_base + MX1_PWMC);
|
||||
|
||||
if (enable)
|
||||
val |= MX1_PWMC_EN;
|
||||
else
|
||||
val &= ~MX1_PWMC_EN;
|
||||
|
||||
val &= ~MX1_PWMC_EN;
|
||||
writel(val, imx->mmio_base + MX1_PWMC);
|
||||
}
|
||||
|
||||
static int imx_pwm_config_v2(struct pwm_chip *chip,
|
||||
struct pwm_device *pwm, int duty_ns, int period_ns)
|
||||
{
|
||||
struct imx_chip *imx = to_imx_chip(chip);
|
||||
struct device *dev = chip->dev;
|
||||
unsigned long long c;
|
||||
unsigned long period_cycles, duty_cycles, prescale;
|
||||
unsigned int period_ms;
|
||||
bool enable = pwm_is_enabled(pwm);
|
||||
int wait_count = 0, fifoav;
|
||||
u32 cr, sr;
|
||||
|
||||
/*
|
||||
* i.MX PWMv2 has a 4-word sample FIFO.
|
||||
* In order to avoid FIFO overflow issue, we do software reset
|
||||
* to clear all sample FIFO if the controller is disabled or
|
||||
* wait for a full PWM cycle to get a relinquished FIFO slot
|
||||
* when the controller is enabled and the FIFO is fully loaded.
|
||||
*/
|
||||
if (enable) {
|
||||
sr = readl(imx->mmio_base + MX3_PWMSR);
|
||||
fifoav = sr & MX3_PWMSR_FIFOAV_MASK;
|
||||
if (fifoav == MX3_PWMSR_FIFOAV_4WORDS) {
|
||||
period_ms = DIV_ROUND_UP(pwm_get_period(pwm),
|
||||
NSEC_PER_MSEC);
|
||||
msleep(period_ms);
|
||||
|
||||
sr = readl(imx->mmio_base + MX3_PWMSR);
|
||||
if (fifoav == (sr & MX3_PWMSR_FIFOAV_MASK))
|
||||
dev_warn(dev, "there is no free FIFO slot\n");
|
||||
}
|
||||
} else {
|
||||
writel(MX3_PWMCR_SWR, imx->mmio_base + MX3_PWMCR);
|
||||
do {
|
||||
usleep_range(200, 1000);
|
||||
cr = readl(imx->mmio_base + MX3_PWMCR);
|
||||
} while ((cr & MX3_PWMCR_SWR) &&
|
||||
(wait_count++ < MX3_PWM_SWR_LOOP));
|
||||
|
||||
if (cr & MX3_PWMCR_SWR)
|
||||
dev_warn(dev, "software reset timeout\n");
|
||||
}
|
||||
|
||||
c = clk_get_rate(imx->clk_per);
|
||||
c = c * period_ns;
|
||||
do_div(c, 1000000000);
|
||||
period_cycles = c;
|
||||
|
||||
prescale = period_cycles / 0x10000 + 1;
|
||||
|
||||
period_cycles /= prescale;
|
||||
c = (unsigned long long)period_cycles * duty_ns;
|
||||
do_div(c, period_ns);
|
||||
duty_cycles = c;
|
||||
|
||||
/*
|
||||
* according to imx pwm RM, the real period value should be
|
||||
* PERIOD value in PWMPR plus 2.
|
||||
*/
|
||||
if (period_cycles > 2)
|
||||
period_cycles -= 2;
|
||||
else
|
||||
period_cycles = 0;
|
||||
|
||||
writel(duty_cycles, imx->mmio_base + MX3_PWMSAR);
|
||||
writel(period_cycles, imx->mmio_base + MX3_PWMPR);
|
||||
|
||||
cr = MX3_PWMCR_PRESCALER(prescale) |
|
||||
MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN |
|
||||
MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC_IPG_HIGH;
|
||||
|
||||
if (enable)
|
||||
cr |= MX3_PWMCR_EN;
|
||||
|
||||
writel(cr, imx->mmio_base + MX3_PWMCR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void imx_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
|
||||
{
|
||||
struct imx_chip *imx = to_imx_chip(chip);
|
||||
u32 val;
|
||||
|
||||
val = readl(imx->mmio_base + MX3_PWMCR);
|
||||
|
||||
if (enable)
|
||||
val |= MX3_PWMCR_EN;
|
||||
else
|
||||
val &= ~MX3_PWMCR_EN;
|
||||
|
||||
writel(val, imx->mmio_base + MX3_PWMCR);
|
||||
}
|
||||
|
||||
static int imx_pwm_config(struct pwm_chip *chip,
|
||||
struct pwm_device *pwm, int duty_ns, int period_ns)
|
||||
{
|
||||
struct imx_chip *imx = to_imx_chip(chip);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(imx->clk_ipg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = imx->config(chip, pwm, duty_ns, period_ns);
|
||||
|
||||
clk_disable_unprepare(imx->clk_ipg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int imx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
{
|
||||
struct imx_chip *imx = to_imx_chip(chip);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(imx->clk_per);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
imx->set_enable(chip, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void imx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
{
|
||||
struct imx_chip *imx = to_imx_chip(chip);
|
||||
|
||||
imx->set_enable(chip, false);
|
||||
|
||||
clk_disable_unprepare(imx->clk_per);
|
||||
}
|
||||
|
||||
static struct pwm_ops imx_pwm_ops = {
|
||||
.enable = imx_pwm_enable,
|
||||
.disable = imx_pwm_disable,
|
||||
.config = imx_pwm_config,
|
||||
static void imx_pwm_sw_reset(struct pwm_chip *chip)
|
||||
{
|
||||
struct imx_chip *imx = to_imx_chip(chip);
|
||||
struct device *dev = chip->dev;
|
||||
int wait_count = 0;
|
||||
u32 cr;
|
||||
|
||||
writel(MX3_PWMCR_SWR, imx->mmio_base + MX3_PWMCR);
|
||||
do {
|
||||
usleep_range(200, 1000);
|
||||
cr = readl(imx->mmio_base + MX3_PWMCR);
|
||||
} while ((cr & MX3_PWMCR_SWR) &&
|
||||
(wait_count++ < MX3_PWM_SWR_LOOP));
|
||||
|
||||
if (cr & MX3_PWMCR_SWR)
|
||||
dev_warn(dev, "software reset timeout\n");
|
||||
}
|
||||
|
||||
static void imx_pwm_wait_fifo_slot(struct pwm_chip *chip,
|
||||
struct pwm_device *pwm)
|
||||
{
|
||||
struct imx_chip *imx = to_imx_chip(chip);
|
||||
struct device *dev = chip->dev;
|
||||
unsigned int period_ms;
|
||||
int fifoav;
|
||||
u32 sr;
|
||||
|
||||
sr = readl(imx->mmio_base + MX3_PWMSR);
|
||||
fifoav = sr & MX3_PWMSR_FIFOAV_MASK;
|
||||
if (fifoav == MX3_PWMSR_FIFOAV_4WORDS) {
|
||||
period_ms = DIV_ROUND_UP(pwm_get_period(pwm),
|
||||
NSEC_PER_MSEC);
|
||||
msleep(period_ms);
|
||||
|
||||
sr = readl(imx->mmio_base + MX3_PWMSR);
|
||||
if (fifoav == (sr & MX3_PWMSR_FIFOAV_MASK))
|
||||
dev_warn(dev, "there is no free FIFO slot\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int imx_pwm_apply_v2(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
struct pwm_state *state)
|
||||
{
|
||||
unsigned long period_cycles, duty_cycles, prescale;
|
||||
struct imx_chip *imx = to_imx_chip(chip);
|
||||
struct pwm_state cstate;
|
||||
unsigned long long c;
|
||||
int ret;
|
||||
u32 cr;
|
||||
|
||||
pwm_get_state(pwm, &cstate);
|
||||
|
||||
if (state->enabled) {
|
||||
c = clk_get_rate(imx->clk_per);
|
||||
c *= state->period;
|
||||
|
||||
do_div(c, 1000000000);
|
||||
period_cycles = c;
|
||||
|
||||
prescale = period_cycles / 0x10000 + 1;
|
||||
|
||||
period_cycles /= prescale;
|
||||
c = (unsigned long long)period_cycles * state->duty_cycle;
|
||||
do_div(c, state->period);
|
||||
duty_cycles = c;
|
||||
|
||||
/*
|
||||
* according to imx pwm RM, the real period value should be
|
||||
* PERIOD value in PWMPR plus 2.
|
||||
*/
|
||||
if (period_cycles > 2)
|
||||
period_cycles -= 2;
|
||||
else
|
||||
period_cycles = 0;
|
||||
|
||||
/*
|
||||
* Wait for a free FIFO slot if the PWM is already enabled, and
|
||||
* flush the FIFO if the PWM was disabled and is about to be
|
||||
* enabled.
|
||||
*/
|
||||
if (cstate.enabled) {
|
||||
imx_pwm_wait_fifo_slot(chip, pwm);
|
||||
} else {
|
||||
ret = clk_prepare_enable(imx->clk_per);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
imx_pwm_sw_reset(chip);
|
||||
}
|
||||
|
||||
writel(duty_cycles, imx->mmio_base + MX3_PWMSAR);
|
||||
writel(period_cycles, imx->mmio_base + MX3_PWMPR);
|
||||
|
||||
cr = MX3_PWMCR_PRESCALER(prescale) |
|
||||
MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN |
|
||||
MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC_IPG_HIGH |
|
||||
MX3_PWMCR_EN;
|
||||
|
||||
if (state->polarity == PWM_POLARITY_INVERSED)
|
||||
cr |= MX3_PWMCR_POUTC;
|
||||
|
||||
writel(cr, imx->mmio_base + MX3_PWMCR);
|
||||
} else if (cstate.enabled) {
|
||||
writel(0, imx->mmio_base + MX3_PWMCR);
|
||||
|
||||
clk_disable_unprepare(imx->clk_per);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pwm_ops imx_pwm_ops_v1 = {
|
||||
.enable = imx_pwm_enable_v1,
|
||||
.disable = imx_pwm_disable_v1,
|
||||
.config = imx_pwm_config_v1,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static const struct pwm_ops imx_pwm_ops_v2 = {
|
||||
.apply = imx_pwm_apply_v2,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
struct imx_pwm_data {
|
||||
int (*config)(struct pwm_chip *chip,
|
||||
struct pwm_device *pwm, int duty_ns, int period_ns);
|
||||
void (*set_enable)(struct pwm_chip *chip, bool enable);
|
||||
bool polarity_supported;
|
||||
const struct pwm_ops *ops;
|
||||
};
|
||||
|
||||
static struct imx_pwm_data imx_pwm_data_v1 = {
|
||||
.config = imx_pwm_config_v1,
|
||||
.set_enable = imx_pwm_set_enable_v1,
|
||||
.ops = &imx_pwm_ops_v1,
|
||||
};
|
||||
|
||||
static struct imx_pwm_data imx_pwm_data_v2 = {
|
||||
.config = imx_pwm_config_v2,
|
||||
.set_enable = imx_pwm_set_enable_v2,
|
||||
.polarity_supported = true,
|
||||
.ops = &imx_pwm_ops_v2,
|
||||
};
|
||||
|
||||
static const struct of_device_id imx_pwm_dt_ids[] = {
|
||||
|
@ -282,6 +272,8 @@ static int imx_pwm_probe(struct platform_device *pdev)
|
|||
if (!of_id)
|
||||
return -ENODEV;
|
||||
|
||||
data = of_id->data;
|
||||
|
||||
imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL);
|
||||
if (imx == NULL)
|
||||
return -ENOMEM;
|
||||
|
@ -293,28 +285,22 @@ static int imx_pwm_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(imx->clk_per);
|
||||
}
|
||||
|
||||
imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
|
||||
if (IS_ERR(imx->clk_ipg)) {
|
||||
dev_err(&pdev->dev, "getting ipg clock failed with %ld\n",
|
||||
PTR_ERR(imx->clk_ipg));
|
||||
return PTR_ERR(imx->clk_ipg);
|
||||
}
|
||||
|
||||
imx->chip.ops = &imx_pwm_ops;
|
||||
imx->chip.ops = data->ops;
|
||||
imx->chip.dev = &pdev->dev;
|
||||
imx->chip.base = -1;
|
||||
imx->chip.npwm = 1;
|
||||
imx->chip.can_sleep = true;
|
||||
|
||||
if (data->polarity_supported) {
|
||||
dev_dbg(&pdev->dev, "PWM supports output inversion\n");
|
||||
imx->chip.of_xlate = of_pwm_xlate_with_flags;
|
||||
imx->chip.of_pwm_n_cells = 3;
|
||||
}
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
imx->mmio_base = devm_ioremap_resource(&pdev->dev, r);
|
||||
if (IS_ERR(imx->mmio_base))
|
||||
return PTR_ERR(imx->mmio_base);
|
||||
|
||||
data = of_id->data;
|
||||
imx->config = data->config;
|
||||
imx->set_enable = data->set_enable;
|
||||
|
||||
ret = pwmchip_add(&imx->chip);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
|
@ -278,7 +278,6 @@ static int lp3943_pwm_probe(struct platform_device *pdev)
|
|||
lp3943_pwm->chip.dev = &pdev->dev;
|
||||
lp3943_pwm->chip.ops = &lp3943_pwm_ops;
|
||||
lp3943_pwm->chip.npwm = LP3943_NUM_PWMS;
|
||||
lp3943_pwm->chip.can_sleep = true;
|
||||
|
||||
platform_set_drvdata(pdev, lp3943_pwm);
|
||||
|
||||
|
|
|
@ -17,6 +17,27 @@
|
|||
|
||||
#include "pwm-lpss.h"
|
||||
|
||||
/* BayTrail */
|
||||
static const struct pwm_lpss_boardinfo pwm_lpss_byt_info = {
|
||||
.clk_rate = 25000000,
|
||||
.npwm = 1,
|
||||
.base_unit_bits = 16,
|
||||
};
|
||||
|
||||
/* Braswell */
|
||||
static const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
|
||||
.clk_rate = 19200000,
|
||||
.npwm = 1,
|
||||
.base_unit_bits = 16,
|
||||
};
|
||||
|
||||
/* Broxton */
|
||||
static const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = {
|
||||
.clk_rate = 19200000,
|
||||
.npwm = 4,
|
||||
.base_unit_bits = 22,
|
||||
};
|
||||
|
||||
static int pwm_lpss_probe_pci(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
|
@ -80,6 +101,7 @@ static const struct pci_device_id pwm_lpss_pci_ids[] = {
|
|||
{ PCI_VDEVICE(INTEL, 0x1ac8), (unsigned long)&pwm_lpss_bxt_info},
|
||||
{ PCI_VDEVICE(INTEL, 0x2288), (unsigned long)&pwm_lpss_bsw_info},
|
||||
{ PCI_VDEVICE(INTEL, 0x2289), (unsigned long)&pwm_lpss_bsw_info},
|
||||
{ PCI_VDEVICE(INTEL, 0x31c8), (unsigned long)&pwm_lpss_bxt_info},
|
||||
{ PCI_VDEVICE(INTEL, 0x5ac8), (unsigned long)&pwm_lpss_bxt_info},
|
||||
{ },
|
||||
};
|
||||
|
|
|
@ -18,6 +18,27 @@
|
|||
|
||||
#include "pwm-lpss.h"
|
||||
|
||||
/* BayTrail */
|
||||
static const struct pwm_lpss_boardinfo pwm_lpss_byt_info = {
|
||||
.clk_rate = 25000000,
|
||||
.npwm = 1,
|
||||
.base_unit_bits = 16,
|
||||
};
|
||||
|
||||
/* Braswell */
|
||||
static const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
|
||||
.clk_rate = 19200000,
|
||||
.npwm = 1,
|
||||
.base_unit_bits = 16,
|
||||
};
|
||||
|
||||
/* Broxton */
|
||||
static const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = {
|
||||
.clk_rate = 19200000,
|
||||
.npwm = 4,
|
||||
.base_unit_bits = 22,
|
||||
};
|
||||
|
||||
static int pwm_lpss_probe_platform(struct platform_device *pdev)
|
||||
{
|
||||
const struct pwm_lpss_boardinfo *info;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
@ -37,30 +38,6 @@ struct pwm_lpss_chip {
|
|||
const struct pwm_lpss_boardinfo *info;
|
||||
};
|
||||
|
||||
/* BayTrail */
|
||||
const struct pwm_lpss_boardinfo pwm_lpss_byt_info = {
|
||||
.clk_rate = 25000000,
|
||||
.npwm = 1,
|
||||
.base_unit_bits = 16,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(pwm_lpss_byt_info);
|
||||
|
||||
/* Braswell */
|
||||
const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
|
||||
.clk_rate = 19200000,
|
||||
.npwm = 1,
|
||||
.base_unit_bits = 16,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(pwm_lpss_bsw_info);
|
||||
|
||||
/* Broxton */
|
||||
const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = {
|
||||
.clk_rate = 19200000,
|
||||
.npwm = 4,
|
||||
.base_unit_bits = 22,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(pwm_lpss_bxt_info);
|
||||
|
||||
static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip)
|
||||
{
|
||||
return container_of(chip, struct pwm_lpss_chip, chip);
|
||||
|
@ -80,17 +57,42 @@ static inline void pwm_lpss_write(const struct pwm_device *pwm, u32 value)
|
|||
writel(value, lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM);
|
||||
}
|
||||
|
||||
static void pwm_lpss_update(struct pwm_device *pwm)
|
||||
static int pwm_lpss_update(struct pwm_device *pwm)
|
||||
{
|
||||
struct pwm_lpss_chip *lpwm = to_lpwm(pwm->chip);
|
||||
const void __iomem *addr = lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM;
|
||||
const unsigned int ms = 500 * USEC_PER_MSEC;
|
||||
u32 val;
|
||||
int err;
|
||||
|
||||
pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_SW_UPDATE);
|
||||
/* Give it some time to propagate */
|
||||
usleep_range(10, 50);
|
||||
|
||||
/*
|
||||
* PWM Configuration register has SW_UPDATE bit that is set when a new
|
||||
* configuration is written to the register. The bit is automatically
|
||||
* cleared at the start of the next output cycle by the IP block.
|
||||
*
|
||||
* If one writes a new configuration to the register while it still has
|
||||
* the bit enabled, PWM may freeze. That is, while one can still write
|
||||
* to the register, it won't have an effect. Thus, we try to sleep long
|
||||
* enough that the bit gets cleared and make sure the bit is not
|
||||
* enabled while we update the configuration.
|
||||
*/
|
||||
err = readl_poll_timeout(addr, val, !(val & PWM_SW_UPDATE), 40, ms);
|
||||
if (err)
|
||||
dev_err(pwm->chip->dev, "PWM_SW_UPDATE was not cleared\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
int duty_ns, int period_ns)
|
||||
static inline int pwm_lpss_is_updating(struct pwm_device *pwm)
|
||||
{
|
||||
return (pwm_lpss_read(pwm) & PWM_SW_UPDATE) ? -EBUSY : 0;
|
||||
}
|
||||
|
||||
static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm,
|
||||
int duty_ns, int period_ns)
|
||||
{
|
||||
struct pwm_lpss_chip *lpwm = to_lpwm(chip);
|
||||
unsigned long long on_time_div;
|
||||
unsigned long c = lpwm->info->clk_rate, base_unit_range;
|
||||
unsigned long long base_unit, freq = NSEC_PER_SEC;
|
||||
|
@ -102,62 +104,62 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
|||
* The equation is:
|
||||
* base_unit = round(base_unit_range * freq / c)
|
||||
*/
|
||||
base_unit_range = BIT(lpwm->info->base_unit_bits);
|
||||
base_unit_range = BIT(lpwm->info->base_unit_bits) - 1;
|
||||
freq *= base_unit_range;
|
||||
|
||||
base_unit = DIV_ROUND_CLOSEST_ULL(freq, c);
|
||||
|
||||
if (duty_ns <= 0)
|
||||
duty_ns = 1;
|
||||
on_time_div = 255ULL * duty_ns;
|
||||
do_div(on_time_div, period_ns);
|
||||
on_time_div = 255ULL - on_time_div;
|
||||
|
||||
pm_runtime_get_sync(chip->dev);
|
||||
|
||||
ctrl = pwm_lpss_read(pwm);
|
||||
ctrl &= ~PWM_ON_TIME_DIV_MASK;
|
||||
ctrl &= ~((base_unit_range - 1) << PWM_BASE_UNIT_SHIFT);
|
||||
base_unit &= (base_unit_range - 1);
|
||||
ctrl &= ~(base_unit_range << PWM_BASE_UNIT_SHIFT);
|
||||
base_unit &= base_unit_range;
|
||||
ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT;
|
||||
ctrl |= on_time_div;
|
||||
pwm_lpss_write(pwm, ctrl);
|
||||
|
||||
/*
|
||||
* If the PWM is already enabled we need to notify the hardware
|
||||
* about the change by setting PWM_SW_UPDATE.
|
||||
*/
|
||||
if (pwm_is_enabled(pwm))
|
||||
pwm_lpss_update(pwm);
|
||||
|
||||
pm_runtime_put(chip->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pwm_lpss_enable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
struct pwm_state *state)
|
||||
{
|
||||
pm_runtime_get_sync(chip->dev);
|
||||
struct pwm_lpss_chip *lpwm = to_lpwm(chip);
|
||||
int ret;
|
||||
|
||||
if (state->enabled) {
|
||||
if (!pwm_is_enabled(pwm)) {
|
||||
pm_runtime_get_sync(chip->dev);
|
||||
ret = pwm_lpss_is_updating(pwm);
|
||||
if (ret) {
|
||||
pm_runtime_put(chip->dev);
|
||||
return ret;
|
||||
}
|
||||
pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period);
|
||||
ret = pwm_lpss_update(pwm);
|
||||
if (ret) {
|
||||
pm_runtime_put(chip->dev);
|
||||
return ret;
|
||||
}
|
||||
pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_ENABLE);
|
||||
} else {
|
||||
ret = pwm_lpss_is_updating(pwm);
|
||||
if (ret)
|
||||
return ret;
|
||||
pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period);
|
||||
return pwm_lpss_update(pwm);
|
||||
}
|
||||
} else if (pwm_is_enabled(pwm)) {
|
||||
pwm_lpss_write(pwm, pwm_lpss_read(pwm) & ~PWM_ENABLE);
|
||||
pm_runtime_put(chip->dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hardware must first see PWM_SW_UPDATE before the PWM can be
|
||||
* enabled.
|
||||
*/
|
||||
pwm_lpss_update(pwm);
|
||||
pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_ENABLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pwm_lpss_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
{
|
||||
pwm_lpss_write(pwm, pwm_lpss_read(pwm) & ~PWM_ENABLE);
|
||||
pm_runtime_put(chip->dev);
|
||||
}
|
||||
|
||||
static const struct pwm_ops pwm_lpss_ops = {
|
||||
.config = pwm_lpss_config,
|
||||
.enable = pwm_lpss_enable,
|
||||
.disable = pwm_lpss_disable,
|
||||
.apply = pwm_lpss_apply,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
|
|
@ -24,10 +24,6 @@ struct pwm_lpss_boardinfo {
|
|||
unsigned long base_unit_bits;
|
||||
};
|
||||
|
||||
extern const struct pwm_lpss_boardinfo pwm_lpss_byt_info;
|
||||
extern const struct pwm_lpss_boardinfo pwm_lpss_bsw_info;
|
||||
extern const struct pwm_lpss_boardinfo pwm_lpss_bxt_info;
|
||||
|
||||
struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
|
||||
const struct pwm_lpss_boardinfo *info);
|
||||
int pwm_lpss_remove(struct pwm_lpss_chip *lpwm);
|
||||
|
|
|
@ -151,7 +151,7 @@ static int mxs_pwm_probe(struct platform_device *pdev)
|
|||
mxs->chip.dev = &pdev->dev;
|
||||
mxs->chip.ops = &mxs_pwm_ops;
|
||||
mxs->chip.base = -1;
|
||||
mxs->chip.can_sleep = true;
|
||||
|
||||
ret = of_property_read_u32(np, "fsl,pwm-number", &mxs->chip.npwm);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to get pwm number: %d\n", ret);
|
||||
|
|
|
@ -20,8 +20,10 @@
|
|||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/pwm.h>
|
||||
|
@ -65,7 +67,6 @@
|
|||
#define PCA9685_MAXCHAN 0x10
|
||||
|
||||
#define LED_FULL (1 << 4)
|
||||
#define MODE1_RESTART (1 << 7)
|
||||
#define MODE1_SLEEP (1 << 4)
|
||||
#define MODE2_INVRT (1 << 4)
|
||||
#define MODE2_OUTDRV (1 << 2)
|
||||
|
@ -81,6 +82,10 @@ struct pca9685 {
|
|||
int active_cnt;
|
||||
int duty_ns;
|
||||
int period_ns;
|
||||
#if IS_ENABLED(CONFIG_GPIOLIB)
|
||||
struct mutex lock;
|
||||
struct gpio_chip gpio;
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline struct pca9685 *to_pca(struct pwm_chip *chip)
|
||||
|
@ -88,6 +93,151 @@ static inline struct pca9685 *to_pca(struct pwm_chip *chip)
|
|||
return container_of(chip, struct pca9685, chip);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_GPIOLIB)
|
||||
static int pca9685_pwm_gpio_request(struct gpio_chip *gpio, unsigned int offset)
|
||||
{
|
||||
struct pca9685 *pca = gpiochip_get_data(gpio);
|
||||
struct pwm_device *pwm;
|
||||
|
||||
mutex_lock(&pca->lock);
|
||||
|
||||
pwm = &pca->chip.pwms[offset];
|
||||
|
||||
if (pwm->flags & (PWMF_REQUESTED | PWMF_EXPORTED)) {
|
||||
mutex_unlock(&pca->lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
pwm_set_chip_data(pwm, (void *)1);
|
||||
|
||||
mutex_unlock(&pca->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pca9685_pwm_gpio_free(struct gpio_chip *gpio, unsigned int offset)
|
||||
{
|
||||
struct pca9685 *pca = gpiochip_get_data(gpio);
|
||||
struct pwm_device *pwm;
|
||||
|
||||
mutex_lock(&pca->lock);
|
||||
pwm = &pca->chip.pwms[offset];
|
||||
pwm_set_chip_data(pwm, NULL);
|
||||
mutex_unlock(&pca->lock);
|
||||
}
|
||||
|
||||
static bool pca9685_pwm_is_gpio(struct pca9685 *pca, struct pwm_device *pwm)
|
||||
{
|
||||
bool is_gpio = false;
|
||||
|
||||
mutex_lock(&pca->lock);
|
||||
|
||||
if (pwm->hwpwm >= PCA9685_MAXCHAN) {
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* Check if any of the GPIOs are requested and in that case
|
||||
* prevent using the "all LEDs" channel.
|
||||
*/
|
||||
for (i = 0; i < pca->gpio.ngpio; i++)
|
||||
if (gpiochip_is_requested(&pca->gpio, i)) {
|
||||
is_gpio = true;
|
||||
break;
|
||||
}
|
||||
} else if (pwm_get_chip_data(pwm)) {
|
||||
is_gpio = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&pca->lock);
|
||||
return is_gpio;
|
||||
}
|
||||
|
||||
static int pca9685_pwm_gpio_get(struct gpio_chip *gpio, unsigned int offset)
|
||||
{
|
||||
struct pca9685 *pca = gpiochip_get_data(gpio);
|
||||
struct pwm_device *pwm = &pca->chip.pwms[offset];
|
||||
unsigned int value;
|
||||
|
||||
regmap_read(pca->regmap, LED_N_ON_H(pwm->hwpwm), &value);
|
||||
|
||||
return value & LED_FULL;
|
||||
}
|
||||
|
||||
static void pca9685_pwm_gpio_set(struct gpio_chip *gpio, unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
struct pca9685 *pca = gpiochip_get_data(gpio);
|
||||
struct pwm_device *pwm = &pca->chip.pwms[offset];
|
||||
unsigned int on = value ? LED_FULL : 0;
|
||||
|
||||
/* Clear both OFF registers */
|
||||
regmap_write(pca->regmap, LED_N_OFF_L(pwm->hwpwm), 0);
|
||||
regmap_write(pca->regmap, LED_N_OFF_H(pwm->hwpwm), 0);
|
||||
|
||||
/* Set the full ON bit */
|
||||
regmap_write(pca->regmap, LED_N_ON_H(pwm->hwpwm), on);
|
||||
}
|
||||
|
||||
static int pca9685_pwm_gpio_get_direction(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
/* Always out */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pca9685_pwm_gpio_direction_input(struct gpio_chip *gpio,
|
||||
unsigned int offset)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int pca9685_pwm_gpio_direction_output(struct gpio_chip *gpio,
|
||||
unsigned int offset, int value)
|
||||
{
|
||||
pca9685_pwm_gpio_set(gpio, offset, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The PCA9685 has a bit for turning the PWM output full off or on. Some
|
||||
* boards like Intel Galileo actually uses these as normal GPIOs so we
|
||||
* expose a GPIO chip here which can exclusively take over the underlying
|
||||
* PWM channel.
|
||||
*/
|
||||
static int pca9685_pwm_gpio_probe(struct pca9685 *pca)
|
||||
{
|
||||
struct device *dev = pca->chip.dev;
|
||||
|
||||
mutex_init(&pca->lock);
|
||||
|
||||
pca->gpio.label = dev_name(dev);
|
||||
pca->gpio.parent = dev;
|
||||
pca->gpio.request = pca9685_pwm_gpio_request;
|
||||
pca->gpio.free = pca9685_pwm_gpio_free;
|
||||
pca->gpio.get_direction = pca9685_pwm_gpio_get_direction;
|
||||
pca->gpio.direction_input = pca9685_pwm_gpio_direction_input;
|
||||
pca->gpio.direction_output = pca9685_pwm_gpio_direction_output;
|
||||
pca->gpio.get = pca9685_pwm_gpio_get;
|
||||
pca->gpio.set = pca9685_pwm_gpio_set;
|
||||
pca->gpio.base = -1;
|
||||
pca->gpio.ngpio = PCA9685_MAXCHAN;
|
||||
pca->gpio.can_sleep = true;
|
||||
|
||||
return devm_gpiochip_add_data(dev, &pca->gpio, pca);
|
||||
}
|
||||
#else
|
||||
static inline bool pca9685_pwm_is_gpio(struct pca9685 *pca,
|
||||
struct pwm_device *pwm)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int pca9685_pwm_gpio_probe(struct pca9685 *pca)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int pca9685_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
int duty_ns, int period_ns)
|
||||
{
|
||||
|
@ -117,16 +267,6 @@ static int pca9685_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
|||
udelay(500);
|
||||
|
||||
pca->period_ns = period_ns;
|
||||
|
||||
/*
|
||||
* If the duty cycle did not change, restart PWM with
|
||||
* the same duty cycle to period ratio and return.
|
||||
*/
|
||||
if (duty_ns == pca->duty_ns) {
|
||||
regmap_update_bits(pca->regmap, PCA9685_MODE1,
|
||||
MODE1_RESTART, 0x1);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
dev_err(chip->dev,
|
||||
"prescaler not set: period out of bounds!\n");
|
||||
|
@ -264,6 +404,9 @@ static int pca9685_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
|
|||
{
|
||||
struct pca9685 *pca = to_pca(chip);
|
||||
|
||||
if (pca9685_pwm_is_gpio(pca, pwm))
|
||||
return -EBUSY;
|
||||
|
||||
if (pca->active_cnt++ == 0)
|
||||
return regmap_update_bits(pca->regmap, PCA9685_MODE1,
|
||||
MODE1_SLEEP, 0x0);
|
||||
|
@ -343,9 +486,16 @@ static int pca9685_pwm_probe(struct i2c_client *client,
|
|||
|
||||
pca->chip.dev = &client->dev;
|
||||
pca->chip.base = -1;
|
||||
pca->chip.can_sleep = true;
|
||||
|
||||
return pwmchip_add(&pca->chip);
|
||||
ret = pwmchip_add(&pca->chip);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = pca9685_pwm_gpio_probe(pca);
|
||||
if (ret < 0)
|
||||
pwmchip_remove(&pca->chip);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pca9685_pwm_remove(struct i2c_client *client)
|
||||
|
|
|
@ -118,7 +118,7 @@ static void pxa_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
|||
clk_disable_unprepare(pc->clk);
|
||||
}
|
||||
|
||||
static struct pwm_ops pxa_pwm_ops = {
|
||||
static const struct pwm_ops pxa_pwm_ops = {
|
||||
.config = pxa_pwm_config,
|
||||
.enable = pxa_pwm_enable,
|
||||
.disable = pxa_pwm_disable,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue