mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'pull-ppc-for-9.0-20240224' of https://gitlab.com/npiggin/qemu into staging
* Avocado tests for ppc64 to boot FreeBSD, run guests with emulated or nested hypervisor facilities, among other things. * Update ppc64 CPU defaults to Power10. * Add a new powernv10-rainier machine to better capture differences between the different Power10 systems. * Implement more device models for powernv. * 4xx TLB flushing performance and correctness improvements. * Correct gdb implementation to access some important SPRs. * Misc cleanups and bug fixes. # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCgAdFiEETkN92lZhb0MpsKeVZ7MCdqhiHK4FAmXYuX0ACgkQZ7MCdqhi # HK6t1Q/9Hxw+MseFUa/6sbWX6mhv/8emrFFOwI9qxapxDoMyic+SjIhR5PPCYh6t # TLE1vJiV54XYB3286hz3eQfDxfHNjkgsF7PYp9SEd6D1rMT9ESxeu5NkifenEfP0 # UoTFXJyfg/OF1h+JQRrVv1m+D4mqGGNCQB4QiU3DYTmRhrhp7H3mKfUX/KvkEwiX # EqZibmrqb9SVSjT66LBQzY328mEH4nipF33QtYKfYjb6kMe8ACSznL2VYP0NmacU # T+3eHJeLtOLeRlHwYfADx2ekRHlsJuE9/fMMHJHb2qxJkHSQ7yGBqSLESAe6kNP8 # TnKJ9x4433K7IjFqaoiDONrMVJbVZDh/DUh1WWdY14iiUOYEy7uLkLtmThmNSyUB # 622Rd5Ch09JWzA/tg1aC9mR2f9boe9/Z1VeHeN8j+sVj1e6MEh8un8SER3X+9TDz # myGLsmPXQnu1yjebycuE+9RAPbR9npOAkQpE5ZfDwjUM7y4s4jzZUKUoIhtCXeEF # eIykVnaGbPlEBGpuf+E+w2ZxhZUIfxRUhuunK8Ib4TE8khJn/Ir4BxoLweSnqtKM # O4xiFvHm72RUVK232Kox5HWbFJ8XSLBUb3ABNGbXXynzAMD+THB4ImFBbysOmIkR # xcF1tWQ+xoMMcCxbx73b0PhO5AR/PgYc2ctug9rAc9fh4ypJLEs= # =LZzb # -----END PGP SIGNATURE----- # gpg: Signature made Fri 23 Feb 2024 15:27:57 GMT # gpg: using RSA key 4E437DDA56616F4329B0A79567B30276A8621CAE # gpg: Good signature from "Nicholas Piggin <npiggin@gmail.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 4E43 7DDA 5661 6F43 29B0 A795 67B3 0276 A862 1CAE * tag 'pull-ppc-for-9.0-20240224' of https://gitlab.com/npiggin/qemu: (47 commits) target/ppc: optimise ppcemb_tlb_t flushing target/ppc: 440 optimise tlbwe TLB flushing target/ppc: 4xx optimise tlbwe_lo TLB flushing target/ppc: 4xx don't flush TLB for a newly written software TLB entry target/ppc: Factor out 4xx ppcemb_tlb_t flushing target/ppc: Fix 440 tlbwe TLB invalidation gaps target/ppc: Add SMT support to time facilities target/ppc: Implement core timebase state machine and TFMR ppc/pnv: Implement the ChipTOD to Core transfer ppc/pnv: Wire ChipTOD model to powernv9 and powernv10 machines ppc/pnv: Add POWER9/10 chiptod model target/ppc: Fix move-to timebase SPR access permissions target/ppc: Improve timebase register defines naming target/ppc: Rename TBL to TB on 64-bit target/ppc: Update gdbstub to read SPR's CFAR, DEC, HDEC, TB-L/U hw/ppc: N1 chiplet wiring hw/ppc: Add N1 chiplet model hw/ppc: Add pnv nest pervasive common chiplet model ppc/pnv: Test pnv i2c master and connected devices ppc/pnv: Add a pca9554 I2C device to powernv10-rainier ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+9
-2
@@ -1170,9 +1170,7 @@ R: Joel Stanley <joel@jms.id.au>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/*/*aspeed*
|
||||
F: hw/misc/pca9552.c
|
||||
F: include/hw/*/*aspeed*
|
||||
F: include/hw/misc/pca9552*.h
|
||||
F: hw/net/ftgmac100.c
|
||||
F: include/hw/net/ftgmac100.h
|
||||
F: docs/system/arm/aspeed.rst
|
||||
@@ -1526,6 +1524,7 @@ F: tests/qtest/libqos/*spapr*
|
||||
F: tests/qtest/rtas*
|
||||
F: tests/qtest/libqos/rtas*
|
||||
F: tests/avocado/ppc_pseries.py
|
||||
F: tests/avocado/ppc_hv_tests.py
|
||||
|
||||
PowerNV (Non-Virtualized)
|
||||
M: Cédric Le Goater <clg@kaod.org>
|
||||
@@ -1543,6 +1542,14 @@ F: include/hw/pci-host/pnv*
|
||||
F: pc-bios/skiboot.lid
|
||||
F: tests/qtest/pnv*
|
||||
|
||||
pca955x
|
||||
M: Glenn Miles <milesg@linux.vnet.ibm.com>
|
||||
L: qemu-ppc@nongnu.org
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/misc/pca955*.c
|
||||
F: include/hw/misc/pca955*.h
|
||||
|
||||
virtex_ml507
|
||||
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||
L: qemu-ppc@nongnu.org
|
||||
|
||||
@@ -229,6 +229,14 @@ The Nios II architecture is orphan.
|
||||
The machine is no longer in existence and has been long unmaintained
|
||||
in QEMU. This also holds for the TC51828 16MiB flash that it uses.
|
||||
|
||||
``pseries-2.1`` up to ``pseries-2.11`` (since 9.0)
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
Older pseries machines before version 2.12 have undergone many changes
|
||||
to correct issues, mostly regarding migration compatibility. These are
|
||||
no longer maintained and removing them will make the code easier to
|
||||
read and maintain. Use versions 2.12 and above as a replacement.
|
||||
|
||||
Backend options
|
||||
---------------
|
||||
|
||||
|
||||
@@ -1346,6 +1346,17 @@ the environment.
|
||||
The definition of *large* is a bit arbitrary here, but it usually means an
|
||||
asset which occupies at least 1GB of size on disk when uncompressed.
|
||||
|
||||
SPEED
|
||||
^^^^^
|
||||
Tests which have a long runtime will not be run unless ``SPEED=slow`` is
|
||||
exported on the environment.
|
||||
|
||||
The definition of *long* is a bit arbitrary here, and it depends on the
|
||||
usefulness of the test too. A unique test is worth spending more time on,
|
||||
small variations on existing tests perhaps less so. As a rough guide,
|
||||
a test or set of similar tests which take more than 100 seconds to
|
||||
complete.
|
||||
|
||||
AVOCADO_ALLOW_UNTRUSTED_CODE
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
There are tests which will boot a kernel image or firmware that can be
|
||||
|
||||
@@ -34,6 +34,10 @@ config PCA9552
|
||||
bool
|
||||
depends on I2C
|
||||
|
||||
config PCA9554
|
||||
bool
|
||||
depends on I2C
|
||||
|
||||
config I2C_ECHO
|
||||
bool
|
||||
default y if TEST_DEVICES
|
||||
|
||||
@@ -4,6 +4,7 @@ system_ss.add(when: 'CONFIG_FW_CFG_DMA', if_true: files('vmcoreinfo.c'))
|
||||
system_ss.add(when: 'CONFIG_ISA_DEBUG', if_true: files('debugexit.c'))
|
||||
system_ss.add(when: 'CONFIG_ISA_TESTDEV', if_true: files('pc-testdev.c'))
|
||||
system_ss.add(when: 'CONFIG_PCA9552', if_true: files('pca9552.c'))
|
||||
system_ss.add(when: 'CONFIG_PCA9554', if_true: files('pca9554.c'))
|
||||
system_ss.add(when: 'CONFIG_PCI_TESTDEV', if_true: files('pci-testdev.c'))
|
||||
system_ss.add(when: 'CONFIG_UNIMP', if_true: files('unimp.c'))
|
||||
system_ss.add(when: 'CONFIG_EMPTY_SLOT', if_true: files('empty_slot.c'))
|
||||
|
||||
+51
-7
@@ -36,11 +36,16 @@ typedef struct PCA955xClass PCA955xClass;
|
||||
|
||||
DECLARE_CLASS_CHECKERS(PCA955xClass, PCA955X,
|
||||
TYPE_PCA955X)
|
||||
|
||||
/*
|
||||
* Note: The LED_ON and LED_OFF configuration values for the PCA955X
|
||||
* chips are the reverse of the PCA953X family of chips.
|
||||
*/
|
||||
#define PCA9552_LED_ON 0x0
|
||||
#define PCA9552_LED_OFF 0x1
|
||||
#define PCA9552_LED_PWM0 0x2
|
||||
#define PCA9552_LED_PWM1 0x3
|
||||
#define PCA9552_PIN_LOW 0x0
|
||||
#define PCA9552_PIN_HIZ 0x1
|
||||
|
||||
static const char *led_state[] = {"on", "off", "pwm0", "pwm1"};
|
||||
|
||||
@@ -107,17 +112,27 @@ static void pca955x_update_pin_input(PCA955xState *s)
|
||||
|
||||
for (i = 0; i < k->pin_count; i++) {
|
||||
uint8_t input_reg = PCA9552_INPUT0 + (i / 8);
|
||||
uint8_t input_shift = (i % 8);
|
||||
uint8_t bit_mask = 1 << (i % 8);
|
||||
uint8_t config = pca955x_pin_get_config(s, i);
|
||||
uint8_t old_value = s->regs[input_reg] & bit_mask;
|
||||
uint8_t new_value;
|
||||
|
||||
switch (config) {
|
||||
case PCA9552_LED_ON:
|
||||
qemu_set_irq(s->gpio[i], 1);
|
||||
s->regs[input_reg] |= 1 << input_shift;
|
||||
/* Pin is set to 0V to turn on LED */
|
||||
s->regs[input_reg] &= ~bit_mask;
|
||||
break;
|
||||
case PCA9552_LED_OFF:
|
||||
qemu_set_irq(s->gpio[i], 0);
|
||||
s->regs[input_reg] &= ~(1 << input_shift);
|
||||
/*
|
||||
* Pin is set to Hi-Z to turn off LED and
|
||||
* pullup sets it to a logical 1 unless
|
||||
* external device drives it low.
|
||||
*/
|
||||
if (s->ext_state[i] == PCA9552_PIN_LOW) {
|
||||
s->regs[input_reg] &= ~bit_mask;
|
||||
} else {
|
||||
s->regs[input_reg] |= bit_mask;
|
||||
}
|
||||
break;
|
||||
case PCA9552_LED_PWM0:
|
||||
case PCA9552_LED_PWM1:
|
||||
@@ -125,6 +140,12 @@ static void pca955x_update_pin_input(PCA955xState *s)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* update irq state only if pin state changed */
|
||||
new_value = s->regs[input_reg] & bit_mask;
|
||||
if (new_value != old_value) {
|
||||
qemu_set_irq(s->gpio_out[i], !!new_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,6 +353,7 @@ static const VMStateDescription pca9552_vmstate = {
|
||||
VMSTATE_UINT8(len, PCA955xState),
|
||||
VMSTATE_UINT8(pointer, PCA955xState),
|
||||
VMSTATE_UINT8_ARRAY(regs, PCA955xState, PCA955X_NR_REGS),
|
||||
VMSTATE_UINT8_ARRAY(ext_state, PCA955xState, PCA955X_PIN_COUNT_MAX),
|
||||
VMSTATE_I2C_SLAVE(i2c, PCA955xState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
@@ -350,6 +372,7 @@ static void pca9552_reset(DeviceState *dev)
|
||||
s->regs[PCA9552_LS2] = 0x55;
|
||||
s->regs[PCA9552_LS3] = 0x55;
|
||||
|
||||
memset(s->ext_state, PCA9552_PIN_HIZ, PCA955X_PIN_COUNT_MAX);
|
||||
pca955x_update_pin_input(s);
|
||||
|
||||
s->pointer = 0xFF;
|
||||
@@ -372,6 +395,26 @@ static void pca955x_initfn(Object *obj)
|
||||
}
|
||||
}
|
||||
|
||||
static void pca955x_set_ext_state(PCA955xState *s, int pin, int level)
|
||||
{
|
||||
if (s->ext_state[pin] != level) {
|
||||
uint16_t pins_status = pca955x_pins_get_status(s);
|
||||
s->ext_state[pin] = level;
|
||||
pca955x_update_pin_input(s);
|
||||
pca955x_display_pins_status(s, pins_status);
|
||||
}
|
||||
}
|
||||
|
||||
static void pca955x_gpio_in_handler(void *opaque, int pin, int level)
|
||||
{
|
||||
|
||||
PCA955xState *s = PCA955X(opaque);
|
||||
PCA955xClass *k = PCA955X_GET_CLASS(s);
|
||||
|
||||
assert((pin >= 0) && (pin < k->pin_count));
|
||||
pca955x_set_ext_state(s, pin, level);
|
||||
}
|
||||
|
||||
static void pca955x_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PCA955xClass *k = PCA955X_GET_CLASS(dev);
|
||||
@@ -381,7 +424,8 @@ static void pca955x_realize(DeviceState *dev, Error **errp)
|
||||
s->description = g_strdup("pca-unspecified");
|
||||
}
|
||||
|
||||
qdev_init_gpio_out(dev, s->gpio, k->pin_count);
|
||||
qdev_init_gpio_out(dev, s->gpio_out, k->pin_count);
|
||||
qdev_init_gpio_in(dev, pca955x_gpio_in_handler, k->pin_count);
|
||||
}
|
||||
|
||||
static Property pca955x_properties[] = {
|
||||
|
||||
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* PCA9554 I/O port
|
||||
*
|
||||
* Copyright (c) 2023, IBM Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/misc/pca9554.h"
|
||||
#include "hw/misc/pca9554_regs.h"
|
||||
#include "hw/irq.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "trace.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
struct PCA9554Class {
|
||||
/*< private >*/
|
||||
I2CSlaveClass parent_class;
|
||||
/*< public >*/
|
||||
};
|
||||
typedef struct PCA9554Class PCA9554Class;
|
||||
|
||||
DECLARE_CLASS_CHECKERS(PCA9554Class, PCA9554,
|
||||
TYPE_PCA9554)
|
||||
|
||||
#define PCA9554_PIN_LOW 0x0
|
||||
#define PCA9554_PIN_HIZ 0x1
|
||||
|
||||
static const char *pin_state[] = {"low", "high"};
|
||||
|
||||
static void pca9554_update_pin_input(PCA9554State *s)
|
||||
{
|
||||
int i;
|
||||
uint8_t config = s->regs[PCA9554_CONFIG];
|
||||
uint8_t output = s->regs[PCA9554_OUTPUT];
|
||||
uint8_t internal_state = config | output;
|
||||
|
||||
for (i = 0; i < PCA9554_PIN_COUNT; i++) {
|
||||
uint8_t bit_mask = 1 << i;
|
||||
uint8_t internal_pin_state = (internal_state >> i) & 0x1;
|
||||
uint8_t old_value = s->regs[PCA9554_INPUT] & bit_mask;
|
||||
uint8_t new_value;
|
||||
|
||||
switch (internal_pin_state) {
|
||||
case PCA9554_PIN_LOW:
|
||||
s->regs[PCA9554_INPUT] &= ~bit_mask;
|
||||
break;
|
||||
case PCA9554_PIN_HIZ:
|
||||
/*
|
||||
* pullup sets it to a logical 1 unless
|
||||
* external device drives it low.
|
||||
*/
|
||||
if (s->ext_state[i] == PCA9554_PIN_LOW) {
|
||||
s->regs[PCA9554_INPUT] &= ~bit_mask;
|
||||
} else {
|
||||
s->regs[PCA9554_INPUT] |= bit_mask;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* update irq state only if pin state changed */
|
||||
new_value = s->regs[PCA9554_INPUT] & bit_mask;
|
||||
if (new_value != old_value) {
|
||||
if (new_value) {
|
||||
/* changed from 0 to 1 */
|
||||
qemu_set_irq(s->gpio_out[i], 1);
|
||||
} else {
|
||||
/* changed from 1 to 0 */
|
||||
qemu_set_irq(s->gpio_out[i], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t pca9554_read(PCA9554State *s, uint8_t reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case PCA9554_INPUT:
|
||||
return s->regs[PCA9554_INPUT] ^ s->regs[PCA9554_POLARITY];
|
||||
case PCA9554_OUTPUT:
|
||||
case PCA9554_POLARITY:
|
||||
case PCA9554_CONFIG:
|
||||
return s->regs[reg];
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: unexpected read to register %d\n",
|
||||
__func__, reg);
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
static void pca9554_write(PCA9554State *s, uint8_t reg, uint8_t data)
|
||||
{
|
||||
switch (reg) {
|
||||
case PCA9554_OUTPUT:
|
||||
case PCA9554_CONFIG:
|
||||
s->regs[reg] = data;
|
||||
pca9554_update_pin_input(s);
|
||||
break;
|
||||
case PCA9554_POLARITY:
|
||||
s->regs[reg] = data;
|
||||
break;
|
||||
case PCA9554_INPUT:
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: unexpected write to register %d\n",
|
||||
__func__, reg);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t pca9554_recv(I2CSlave *i2c)
|
||||
{
|
||||
PCA9554State *s = PCA9554(i2c);
|
||||
uint8_t ret;
|
||||
|
||||
ret = pca9554_read(s, s->pointer & 0x3);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pca9554_send(I2CSlave *i2c, uint8_t data)
|
||||
{
|
||||
PCA9554State *s = PCA9554(i2c);
|
||||
|
||||
/* First byte sent by is the register address */
|
||||
if (s->len == 0) {
|
||||
s->pointer = data;
|
||||
s->len++;
|
||||
} else {
|
||||
pca9554_write(s, s->pointer & 0x3, data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pca9554_event(I2CSlave *i2c, enum i2c_event event)
|
||||
{
|
||||
PCA9554State *s = PCA9554(i2c);
|
||||
|
||||
s->len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pca9554_get_pin(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
PCA9554State *s = PCA9554(obj);
|
||||
int pin, rc;
|
||||
uint8_t state;
|
||||
|
||||
rc = sscanf(name, "pin%2d", &pin);
|
||||
if (rc != 1) {
|
||||
error_setg(errp, "%s: error reading %s", __func__, name);
|
||||
return;
|
||||
}
|
||||
if (pin < 0 || pin > PCA9554_PIN_COUNT) {
|
||||
error_setg(errp, "%s invalid pin %s", __func__, name);
|
||||
return;
|
||||
}
|
||||
|
||||
state = pca9554_read(s, PCA9554_CONFIG);
|
||||
state |= pca9554_read(s, PCA9554_OUTPUT);
|
||||
state = (state >> pin) & 0x1;
|
||||
visit_type_str(v, name, (char **)&pin_state[state], errp);
|
||||
}
|
||||
|
||||
static void pca9554_set_pin(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
PCA9554State *s = PCA9554(obj);
|
||||
int pin, rc, val;
|
||||
uint8_t state, mask;
|
||||
char *state_str;
|
||||
|
||||
if (!visit_type_str(v, name, &state_str, errp)) {
|
||||
return;
|
||||
}
|
||||
rc = sscanf(name, "pin%2d", &pin);
|
||||
if (rc != 1) {
|
||||
error_setg(errp, "%s: error reading %s", __func__, name);
|
||||
return;
|
||||
}
|
||||
if (pin < 0 || pin > PCA9554_PIN_COUNT) {
|
||||
error_setg(errp, "%s invalid pin %s", __func__, name);
|
||||
return;
|
||||
}
|
||||
|
||||
for (state = 0; state < ARRAY_SIZE(pin_state); state++) {
|
||||
if (!strcmp(state_str, pin_state[state])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (state >= ARRAY_SIZE(pin_state)) {
|
||||
error_setg(errp, "%s invalid pin state %s", __func__, state_str);
|
||||
return;
|
||||
}
|
||||
|
||||
/* First, modify the output register bit */
|
||||
val = pca9554_read(s, PCA9554_OUTPUT);
|
||||
mask = 0x1 << pin;
|
||||
if (state == PCA9554_PIN_LOW) {
|
||||
val &= ~(mask);
|
||||
} else {
|
||||
val |= mask;
|
||||
}
|
||||
pca9554_write(s, PCA9554_OUTPUT, val);
|
||||
|
||||
/* Then, clear the config register bit for output mode */
|
||||
val = pca9554_read(s, PCA9554_CONFIG);
|
||||
val &= ~mask;
|
||||
pca9554_write(s, PCA9554_CONFIG, val);
|
||||
}
|
||||
|
||||
static const VMStateDescription pca9554_vmstate = {
|
||||
.name = "PCA9554",
|
||||
.version_id = 0,
|
||||
.minimum_version_id = 0,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT8(len, PCA9554State),
|
||||
VMSTATE_UINT8(pointer, PCA9554State),
|
||||
VMSTATE_UINT8_ARRAY(regs, PCA9554State, PCA9554_NR_REGS),
|
||||
VMSTATE_UINT8_ARRAY(ext_state, PCA9554State, PCA9554_PIN_COUNT),
|
||||
VMSTATE_I2C_SLAVE(i2c, PCA9554State),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void pca9554_reset(DeviceState *dev)
|
||||
{
|
||||
PCA9554State *s = PCA9554(dev);
|
||||
|
||||
s->regs[PCA9554_INPUT] = 0xFF;
|
||||
s->regs[PCA9554_OUTPUT] = 0xFF;
|
||||
s->regs[PCA9554_POLARITY] = 0x0; /* No pins are inverted */
|
||||
s->regs[PCA9554_CONFIG] = 0xFF; /* All pins are inputs */
|
||||
|
||||
memset(s->ext_state, PCA9554_PIN_HIZ, PCA9554_PIN_COUNT);
|
||||
pca9554_update_pin_input(s);
|
||||
|
||||
s->pointer = 0x0;
|
||||
s->len = 0;
|
||||
}
|
||||
|
||||
static void pca9554_initfn(Object *obj)
|
||||
{
|
||||
int pin;
|
||||
|
||||
for (pin = 0; pin < PCA9554_PIN_COUNT; pin++) {
|
||||
char *name;
|
||||
|
||||
name = g_strdup_printf("pin%d", pin);
|
||||
object_property_add(obj, name, "bool", pca9554_get_pin, pca9554_set_pin,
|
||||
NULL, NULL);
|
||||
g_free(name);
|
||||
}
|
||||
}
|
||||
|
||||
static void pca9554_set_ext_state(PCA9554State *s, int pin, int level)
|
||||
{
|
||||
if (s->ext_state[pin] != level) {
|
||||
s->ext_state[pin] = level;
|
||||
pca9554_update_pin_input(s);
|
||||
}
|
||||
}
|
||||
|
||||
static void pca9554_gpio_in_handler(void *opaque, int pin, int level)
|
||||
{
|
||||
|
||||
PCA9554State *s = PCA9554(opaque);
|
||||
|
||||
assert((pin >= 0) && (pin < PCA9554_PIN_COUNT));
|
||||
pca9554_set_ext_state(s, pin, level);
|
||||
}
|
||||
|
||||
static void pca9554_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PCA9554State *s = PCA9554(dev);
|
||||
|
||||
if (!s->description) {
|
||||
s->description = g_strdup("pca9554");
|
||||
}
|
||||
|
||||
qdev_init_gpio_out(dev, s->gpio_out, PCA9554_PIN_COUNT);
|
||||
qdev_init_gpio_in(dev, pca9554_gpio_in_handler, PCA9554_PIN_COUNT);
|
||||
}
|
||||
|
||||
static Property pca9554_properties[] = {
|
||||
DEFINE_PROP_STRING("description", PCA9554State, description),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void pca9554_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
|
||||
|
||||
k->event = pca9554_event;
|
||||
k->recv = pca9554_recv;
|
||||
k->send = pca9554_send;
|
||||
dc->realize = pca9554_realize;
|
||||
dc->reset = pca9554_reset;
|
||||
dc->vmsd = &pca9554_vmstate;
|
||||
device_class_set_props(dc, pca9554_properties);
|
||||
}
|
||||
|
||||
static const TypeInfo pca9554_info = {
|
||||
.name = TYPE_PCA9554,
|
||||
.parent = TYPE_I2C_SLAVE,
|
||||
.instance_init = pca9554_initfn,
|
||||
.instance_size = sizeof(PCA9554State),
|
||||
.class_init = pca9554_class_init,
|
||||
.class_size = sizeof(PCA9554Class),
|
||||
.abstract = false,
|
||||
};
|
||||
|
||||
static void pca9554_register_types(void)
|
||||
{
|
||||
type_register_static(&pca9554_info);
|
||||
}
|
||||
|
||||
type_init(pca9554_register_types)
|
||||
@@ -32,6 +32,8 @@ config POWERNV
|
||||
select XIVE
|
||||
select FDT_PPC
|
||||
select PCI_POWERNV
|
||||
select PCA9552
|
||||
select PCA9554
|
||||
|
||||
config PPC405
|
||||
bool
|
||||
|
||||
+4
-1
@@ -31,7 +31,7 @@ ppc_ss.add(when: 'CONFIG_PSERIES', if_true: files(
|
||||
'pef.c',
|
||||
))
|
||||
ppc_ss.add(when: ['CONFIG_PSERIES', 'CONFIG_TCG'], if_true: files(
|
||||
'spapr_softmmu.c',
|
||||
'spapr_vhyp_mmu.c',
|
||||
))
|
||||
ppc_ss.add(when: 'CONFIG_SPAPR_RNG', if_true: files('spapr_rng.c'))
|
||||
if host_os == 'linux'
|
||||
@@ -48,11 +48,14 @@ ppc_ss.add(when: 'CONFIG_POWERNV', if_true: files(
|
||||
'pnv_i2c.c',
|
||||
'pnv_lpc.c',
|
||||
'pnv_psi.c',
|
||||
'pnv_chiptod.c',
|
||||
'pnv_occ.c',
|
||||
'pnv_sbe.c',
|
||||
'pnv_bmc.c',
|
||||
'pnv_homer.c',
|
||||
'pnv_pnor.c',
|
||||
'pnv_nest_pervasive.c',
|
||||
'pnv_n1_chiplet.c',
|
||||
))
|
||||
# PowerPC 4xx boards
|
||||
ppc_ss.add(when: 'CONFIG_PPC405', if_true: files(
|
||||
|
||||
+127
-4
@@ -790,6 +790,7 @@ static void pnv_init(MachineState *machine)
|
||||
const char *bios_name = machine->firmware ?: FW_FILE_NAME;
|
||||
PnvMachineState *pnv = PNV_MACHINE(machine);
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
|
||||
char *fw_filename;
|
||||
long fw_size;
|
||||
uint64_t chip_ram_start = 0;
|
||||
@@ -979,6 +980,13 @@ static void pnv_init(MachineState *machine)
|
||||
*/
|
||||
pnv->powerdown_notifier.notify = pnv_powerdown_notify;
|
||||
qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
|
||||
|
||||
/*
|
||||
* Create/Connect any machine-specific I2C devices
|
||||
*/
|
||||
if (pmc->i2c_init) {
|
||||
pmc->i2c_init(pnv);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1419,6 +1427,8 @@ static void pnv_chip_power9_instance_init(Object *obj)
|
||||
|
||||
object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC);
|
||||
|
||||
object_initialize_child(obj, "chiptod", &chip9->chiptod, TYPE_PNV9_CHIPTOD);
|
||||
|
||||
object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC);
|
||||
|
||||
object_initialize_child(obj, "sbe", &chip9->sbe, TYPE_PNV9_SBE);
|
||||
@@ -1565,6 +1575,19 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
|
||||
chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
|
||||
(uint64_t) PNV9_LPCM_BASE(chip));
|
||||
|
||||
/* ChipTOD */
|
||||
object_property_set_bool(OBJECT(&chip9->chiptod), "primary",
|
||||
chip->chip_id == 0, &error_abort);
|
||||
object_property_set_bool(OBJECT(&chip9->chiptod), "secondary",
|
||||
chip->chip_id == 1, &error_abort);
|
||||
object_property_set_link(OBJECT(&chip9->chiptod), "chip", OBJECT(chip),
|
||||
&error_abort);
|
||||
if (!qdev_realize(DEVICE(&chip9->chiptod), NULL, errp)) {
|
||||
return;
|
||||
}
|
||||
pnv_xscom_add_subregion(chip, PNV9_XSCOM_CHIPTOD_BASE,
|
||||
&chip9->chiptod.xscom_regs);
|
||||
|
||||
/* Create the simplified OCC model */
|
||||
if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) {
|
||||
return;
|
||||
@@ -1677,9 +1700,13 @@ static void pnv_chip_power10_instance_init(Object *obj)
|
||||
"xive-fabric");
|
||||
object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI);
|
||||
object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC);
|
||||
object_initialize_child(obj, "chiptod", &chip10->chiptod,
|
||||
TYPE_PNV10_CHIPTOD);
|
||||
object_initialize_child(obj, "occ", &chip10->occ, TYPE_PNV10_OCC);
|
||||
object_initialize_child(obj, "sbe", &chip10->sbe, TYPE_PNV10_SBE);
|
||||
object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER);
|
||||
object_initialize_child(obj, "n1-chiplet", &chip10->n1_chiplet,
|
||||
TYPE_PNV_N1_CHIPLET);
|
||||
|
||||
chip->num_pecs = pcc->num_pecs;
|
||||
|
||||
@@ -1810,6 +1837,19 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
|
||||
chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
|
||||
(uint64_t) PNV10_LPCM_BASE(chip));
|
||||
|
||||
/* ChipTOD */
|
||||
object_property_set_bool(OBJECT(&chip10->chiptod), "primary",
|
||||
chip->chip_id == 0, &error_abort);
|
||||
object_property_set_bool(OBJECT(&chip10->chiptod), "secondary",
|
||||
chip->chip_id == 1, &error_abort);
|
||||
object_property_set_link(OBJECT(&chip10->chiptod), "chip", OBJECT(chip),
|
||||
&error_abort);
|
||||
if (!qdev_realize(DEVICE(&chip10->chiptod), NULL, errp)) {
|
||||
return;
|
||||
}
|
||||
pnv_xscom_add_subregion(chip, PNV10_XSCOM_CHIPTOD_BASE,
|
||||
&chip10->chiptod.xscom_regs);
|
||||
|
||||
/* Create the simplified OCC model */
|
||||
if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) {
|
||||
return;
|
||||
@@ -1849,6 +1889,19 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
|
||||
memory_region_add_subregion(get_system_memory(), PNV10_HOMER_BASE(chip),
|
||||
&chip10->homer.regs);
|
||||
|
||||
/* N1 chiplet */
|
||||
if (!qdev_realize(DEVICE(&chip10->n1_chiplet), NULL, errp)) {
|
||||
return;
|
||||
}
|
||||
pnv_xscom_add_subregion(chip, PNV10_XSCOM_N1_CHIPLET_CTRL_REGS_BASE,
|
||||
&chip10->n1_chiplet.nest_pervasive.xscom_ctrl_regs_mr);
|
||||
|
||||
pnv_xscom_add_subregion(chip, PNV10_XSCOM_N1_PB_SCOM_EQ_BASE,
|
||||
&chip10->n1_chiplet.xscom_pb_eq_mr);
|
||||
|
||||
pnv_xscom_add_subregion(chip, PNV10_XSCOM_N1_PB_SCOM_ES_BASE,
|
||||
&chip10->n1_chiplet.xscom_pb_es_mr);
|
||||
|
||||
/* PHBs */
|
||||
pnv_chip_power10_phb_realize(chip, &local_err);
|
||||
if (local_err) {
|
||||
@@ -1879,6 +1932,39 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
|
||||
qdev_get_gpio_in(DEVICE(&chip10->psi),
|
||||
PSIHB9_IRQ_SBE_I2C));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void pnv_rainier_i2c_init(PnvMachineState *pnv)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < pnv->num_chips; i++) {
|
||||
Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]);
|
||||
|
||||
/*
|
||||
* Add a PCA9552 I2C device for PCIe hotplug control
|
||||
* to engine 2, bus 1, address 0x63
|
||||
*/
|
||||
I2CSlave *dev = i2c_slave_create_simple(chip10->i2c[2].busses[1],
|
||||
"pca9552", 0x63);
|
||||
|
||||
/*
|
||||
* Connect PCA9552 GPIO pins 0-4 (SLOTx_EN) outputs to GPIO pins 5-9
|
||||
* (SLOTx_PG) inputs in order to fake the pgood state of PCIe slots
|
||||
* after hypervisor code sets a SLOTx_EN pin high.
|
||||
*/
|
||||
qdev_connect_gpio_out(DEVICE(dev), 0, qdev_get_gpio_in(DEVICE(dev), 5));
|
||||
qdev_connect_gpio_out(DEVICE(dev), 1, qdev_get_gpio_in(DEVICE(dev), 6));
|
||||
qdev_connect_gpio_out(DEVICE(dev), 2, qdev_get_gpio_in(DEVICE(dev), 7));
|
||||
qdev_connect_gpio_out(DEVICE(dev), 3, qdev_get_gpio_in(DEVICE(dev), 8));
|
||||
qdev_connect_gpio_out(DEVICE(dev), 4, qdev_get_gpio_in(DEVICE(dev), 9));
|
||||
|
||||
/*
|
||||
* Add a PCA9554 I2C device for cable card presence detection
|
||||
* to engine 2, bus 1, address 0x25
|
||||
*/
|
||||
i2c_slave_create_simple(chip10->i2c[2].busses[1], "pca9554", 0x25);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
|
||||
@@ -2035,6 +2121,21 @@ static void pnv_chip_class_init(ObjectClass *klass, void *data)
|
||||
dc->desc = "PowerNV Chip";
|
||||
}
|
||||
|
||||
PnvCore *pnv_chip_find_core(PnvChip *chip, uint32_t core_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < chip->nr_cores; i++) {
|
||||
PnvCore *pc = chip->cores[i];
|
||||
CPUCore *cc = CPU_CORE(pc);
|
||||
|
||||
if (cc->core_id == core_id) {
|
||||
return pc;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
|
||||
{
|
||||
int i, j;
|
||||
@@ -2242,8 +2343,6 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
|
||||
|
||||
xfc->match_nvt = pnv_match_nvt;
|
||||
|
||||
mc->alias = "powernv";
|
||||
|
||||
pmc->compat = compat;
|
||||
pmc->compat_size = sizeof(compat);
|
||||
pmc->dt_power_mgt = pnv_dt_power_mgt;
|
||||
@@ -2251,7 +2350,7 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
|
||||
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
|
||||
}
|
||||
|
||||
static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
|
||||
static void pnv_machine_p10_common_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
|
||||
@@ -2263,10 +2362,11 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
|
||||
{ TYPE_PNV_PHB_ROOT_PORT, "version", "5" },
|
||||
};
|
||||
|
||||
mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
|
||||
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
|
||||
compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
|
||||
|
||||
mc->alias = "powernv";
|
||||
|
||||
pmc->compat = compat;
|
||||
pmc->compat_size = sizeof(compat);
|
||||
pmc->dt_power_mgt = pnv_dt_power_mgt;
|
||||
@@ -2276,6 +2376,24 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
|
||||
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
|
||||
}
|
||||
|
||||
static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
|
||||
pnv_machine_p10_common_class_init(oc, data);
|
||||
mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
|
||||
}
|
||||
|
||||
static void pnv_machine_p10_rainier_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
|
||||
|
||||
pnv_machine_p10_common_class_init(oc, data);
|
||||
mc->desc = "IBM PowerNV (Non-Virtualized) POWER10 Rainier";
|
||||
pmc->i2c_init = pnv_rainier_i2c_init;
|
||||
}
|
||||
|
||||
static bool pnv_machine_get_hb(Object *obj, Error **errp)
|
||||
{
|
||||
PnvMachineState *pnv = PNV_MACHINE(obj);
|
||||
@@ -2381,6 +2499,11 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data)
|
||||
}
|
||||
|
||||
static const TypeInfo types[] = {
|
||||
{
|
||||
.name = MACHINE_TYPE_NAME("powernv10-rainier"),
|
||||
.parent = MACHINE_TYPE_NAME("powernv10"),
|
||||
.class_init = pnv_machine_p10_rainier_class_init,
|
||||
},
|
||||
{
|
||||
.name = MACHINE_TYPE_NAME("powernv10"),
|
||||
.parent = TYPE_PNV_MACHINE,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+15
-131
@@ -22,136 +22,7 @@
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
/* I2C FIFO register */
|
||||
#define I2C_FIFO_REG 0x4
|
||||
#define I2C_FIFO PPC_BITMASK(0, 7)
|
||||
|
||||
/* I2C command register */
|
||||
#define I2C_CMD_REG 0x5
|
||||
#define I2C_CMD_WITH_START PPC_BIT(0)
|
||||
#define I2C_CMD_WITH_ADDR PPC_BIT(1)
|
||||
#define I2C_CMD_READ_CONT PPC_BIT(2)
|
||||
#define I2C_CMD_WITH_STOP PPC_BIT(3)
|
||||
#define I2C_CMD_INTR_STEERING PPC_BITMASK(6, 7) /* P9 */
|
||||
#define I2C_CMD_INTR_STEER_HOST 1
|
||||
#define I2C_CMD_INTR_STEER_OCC 2
|
||||
#define I2C_CMD_DEV_ADDR PPC_BITMASK(8, 14)
|
||||
#define I2C_CMD_READ_NOT_WRITE PPC_BIT(15)
|
||||
#define I2C_CMD_LEN_BYTES PPC_BITMASK(16, 31)
|
||||
#define I2C_MAX_TFR_LEN 0xfff0ull
|
||||
|
||||
/* I2C mode register */
|
||||
#define I2C_MODE_REG 0x6
|
||||
#define I2C_MODE_BIT_RATE_DIV PPC_BITMASK(0, 15)
|
||||
#define I2C_MODE_PORT_NUM PPC_BITMASK(16, 21)
|
||||
#define I2C_MODE_ENHANCED PPC_BIT(28)
|
||||
#define I2C_MODE_DIAGNOSTIC PPC_BIT(29)
|
||||
#define I2C_MODE_PACING_ALLOW PPC_BIT(30)
|
||||
#define I2C_MODE_WRAP PPC_BIT(31)
|
||||
|
||||
/* I2C watermark register */
|
||||
#define I2C_WATERMARK_REG 0x7
|
||||
#define I2C_WATERMARK_HIGH PPC_BITMASK(16, 19)
|
||||
#define I2C_WATERMARK_LOW PPC_BITMASK(24, 27)
|
||||
|
||||
/*
|
||||
* I2C interrupt mask and condition registers
|
||||
*
|
||||
* NB: The function of 0x9 and 0xa changes depending on whether you're reading
|
||||
* or writing to them. When read they return the interrupt condition bits
|
||||
* and on writes they update the interrupt mask register.
|
||||
*
|
||||
* The bit definitions are the same for all the interrupt registers.
|
||||
*/
|
||||
#define I2C_INTR_MASK_REG 0x8
|
||||
|
||||
#define I2C_INTR_RAW_COND_REG 0x9 /* read */
|
||||
#define I2C_INTR_MASK_OR_REG 0x9 /* write*/
|
||||
|
||||
#define I2C_INTR_COND_REG 0xa /* read */
|
||||
#define I2C_INTR_MASK_AND_REG 0xa /* write */
|
||||
|
||||
#define I2C_INTR_ALL PPC_BITMASK(16, 31)
|
||||
#define I2C_INTR_INVALID_CMD PPC_BIT(16)
|
||||
#define I2C_INTR_LBUS_PARITY_ERR PPC_BIT(17)
|
||||
#define I2C_INTR_BKEND_OVERRUN_ERR PPC_BIT(18)
|
||||
#define I2C_INTR_BKEND_ACCESS_ERR PPC_BIT(19)
|
||||
#define I2C_INTR_ARBT_LOST_ERR PPC_BIT(20)
|
||||
#define I2C_INTR_NACK_RCVD_ERR PPC_BIT(21)
|
||||
#define I2C_INTR_DATA_REQ PPC_BIT(22)
|
||||
#define I2C_INTR_CMD_COMP PPC_BIT(23)
|
||||
#define I2C_INTR_STOP_ERR PPC_BIT(24)
|
||||
#define I2C_INTR_I2C_BUSY PPC_BIT(25)
|
||||
#define I2C_INTR_NOT_I2C_BUSY PPC_BIT(26)
|
||||
#define I2C_INTR_SCL_EQ_1 PPC_BIT(28)
|
||||
#define I2C_INTR_SCL_EQ_0 PPC_BIT(29)
|
||||
#define I2C_INTR_SDA_EQ_1 PPC_BIT(30)
|
||||
#define I2C_INTR_SDA_EQ_0 PPC_BIT(31)
|
||||
|
||||
/* I2C status register */
|
||||
#define I2C_RESET_I2C_REG 0xb /* write */
|
||||
#define I2C_RESET_ERRORS 0xc
|
||||
#define I2C_STAT_REG 0xb /* read */
|
||||
#define I2C_STAT_INVALID_CMD PPC_BIT(0)
|
||||
#define I2C_STAT_LBUS_PARITY_ERR PPC_BIT(1)
|
||||
#define I2C_STAT_BKEND_OVERRUN_ERR PPC_BIT(2)
|
||||
#define I2C_STAT_BKEND_ACCESS_ERR PPC_BIT(3)
|
||||
#define I2C_STAT_ARBT_LOST_ERR PPC_BIT(4)
|
||||
#define I2C_STAT_NACK_RCVD_ERR PPC_BIT(5)
|
||||
#define I2C_STAT_DATA_REQ PPC_BIT(6)
|
||||
#define I2C_STAT_CMD_COMP PPC_BIT(7)
|
||||
#define I2C_STAT_STOP_ERR PPC_BIT(8)
|
||||
#define I2C_STAT_UPPER_THRS PPC_BITMASK(9, 15)
|
||||
#define I2C_STAT_ANY_I2C_INTR PPC_BIT(16)
|
||||
#define I2C_STAT_PORT_HISTORY_BUSY PPC_BIT(19)
|
||||
#define I2C_STAT_SCL_INPUT_LEVEL PPC_BIT(20)
|
||||
#define I2C_STAT_SDA_INPUT_LEVEL PPC_BIT(21)
|
||||
#define I2C_STAT_PORT_BUSY PPC_BIT(22)
|
||||
#define I2C_STAT_INTERFACE_BUSY PPC_BIT(23)
|
||||
#define I2C_STAT_FIFO_ENTRY_COUNT PPC_BITMASK(24, 31)
|
||||
|
||||
#define I2C_STAT_ANY_ERR (I2C_STAT_INVALID_CMD | I2C_STAT_LBUS_PARITY_ERR | \
|
||||
I2C_STAT_BKEND_OVERRUN_ERR | \
|
||||
I2C_STAT_BKEND_ACCESS_ERR | I2C_STAT_ARBT_LOST_ERR | \
|
||||
I2C_STAT_NACK_RCVD_ERR | I2C_STAT_STOP_ERR)
|
||||
|
||||
|
||||
#define I2C_INTR_ACTIVE \
|
||||
((I2C_STAT_ANY_ERR >> 16) | I2C_INTR_CMD_COMP | I2C_INTR_DATA_REQ)
|
||||
|
||||
/* Pseudo-status used for timeouts */
|
||||
#define I2C_STAT_PSEUDO_TIMEOUT PPC_BIT(63)
|
||||
|
||||
/* I2C extended status register */
|
||||
#define I2C_EXTD_STAT_REG 0xc
|
||||
#define I2C_EXTD_STAT_FIFO_SIZE PPC_BITMASK(0, 7)
|
||||
#define I2C_EXTD_STAT_MSM_CURSTATE PPC_BITMASK(11, 15)
|
||||
#define I2C_EXTD_STAT_SCL_IN_SYNC PPC_BIT(16)
|
||||
#define I2C_EXTD_STAT_SDA_IN_SYNC PPC_BIT(17)
|
||||
#define I2C_EXTD_STAT_S_SCL PPC_BIT(18)
|
||||
#define I2C_EXTD_STAT_S_SDA PPC_BIT(19)
|
||||
#define I2C_EXTD_STAT_M_SCL PPC_BIT(20)
|
||||
#define I2C_EXTD_STAT_M_SDA PPC_BIT(21)
|
||||
#define I2C_EXTD_STAT_HIGH_WATER PPC_BIT(22)
|
||||
#define I2C_EXTD_STAT_LOW_WATER PPC_BIT(23)
|
||||
#define I2C_EXTD_STAT_I2C_BUSY PPC_BIT(24)
|
||||
#define I2C_EXTD_STAT_SELF_BUSY PPC_BIT(25)
|
||||
#define I2C_EXTD_STAT_I2C_VERSION PPC_BITMASK(27, 31)
|
||||
|
||||
/* I2C residual front end/back end length */
|
||||
#define I2C_RESIDUAL_LEN_REG 0xd
|
||||
#define I2C_RESIDUAL_FRONT_END PPC_BITMASK(0, 15)
|
||||
#define I2C_RESIDUAL_BACK_END PPC_BITMASK(16, 31)
|
||||
|
||||
/* Port busy register */
|
||||
#define I2C_PORT_BUSY_REG 0xe
|
||||
#define I2C_SET_S_SCL_REG 0xd
|
||||
#define I2C_RESET_S_SCL_REG 0xf
|
||||
#define I2C_SET_S_SDA_REG 0x10
|
||||
#define I2C_RESET_S_SDA_REG 0x11
|
||||
|
||||
#define PNV_I2C_FIFO_SIZE 8
|
||||
#define PNV_I2C_MAX_BUSSES 64
|
||||
#include "hw/i2c/pnv_i2c_regs.h"
|
||||
|
||||
static I2CBus *pnv_i2c_get_bus(PnvI2C *i2c)
|
||||
{
|
||||
@@ -629,6 +500,19 @@ static int pnv_i2c_dt_xscom(PnvXScomInterface *dev, void *fdt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pnv_i2c_sys_reset(void *dev)
|
||||
{
|
||||
int port;
|
||||
PnvI2C *i2c = PNV_I2C(dev);
|
||||
|
||||
pnv_i2c_reset(dev);
|
||||
|
||||
/* reset all buses connected to this i2c controller */
|
||||
for (port = 0; port < i2c->num_busses; port++) {
|
||||
bus_cold_reset(BUS(i2c->busses[port]));
|
||||
}
|
||||
}
|
||||
|
||||
static void pnv_i2c_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PnvI2C *i2c = PNV_I2C(dev);
|
||||
@@ -654,7 +538,7 @@ static void pnv_i2c_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
fifo8_create(&i2c->fifo, PNV_I2C_FIFO_SIZE);
|
||||
|
||||
qemu_register_reset(pnv_i2c_reset, dev);
|
||||
qemu_register_reset(pnv_i2c_sys_reset, dev);
|
||||
|
||||
qdev_init_gpio_out(DEVICE(dev), &i2c->psi_irq, 1);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* QEMU PowerPC N1 chiplet model
|
||||
*
|
||||
* Copyright (c) 2023, IBM Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/ppc/pnv.h"
|
||||
#include "hw/ppc/pnv_xscom.h"
|
||||
#include "hw/ppc/pnv_n1_chiplet.h"
|
||||
#include "hw/ppc/pnv_nest_pervasive.h"
|
||||
|
||||
/*
|
||||
* The n1 chiplet contains chiplet control unit,
|
||||
* PowerBus/RaceTrack/Bridge logic, nest Memory Management Unit(nMMU)
|
||||
* and more.
|
||||
*
|
||||
* In this model Nest1 chiplet control registers are modelled via common
|
||||
* nest pervasive model and few PowerBus racetrack registers are modelled.
|
||||
*/
|
||||
|
||||
#define PB_SCOM_EQ0_HP_MODE2_CURR 0xe
|
||||
#define PB_SCOM_ES3_MODE 0x8a
|
||||
|
||||
static uint64_t pnv_n1_chiplet_pb_scom_eq_read(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
{
|
||||
PnvN1Chiplet *n1_chiplet = PNV_N1_CHIPLET(opaque);
|
||||
uint32_t reg = addr >> 3;
|
||||
uint64_t val = ~0ull;
|
||||
|
||||
switch (reg) {
|
||||
case PB_SCOM_EQ0_HP_MODE2_CURR:
|
||||
val = n1_chiplet->eq[0].hp_mode2_curr;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "%s: Invalid xscom read at 0x%" PRIx32 "\n",
|
||||
__func__, reg);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void pnv_n1_chiplet_pb_scom_eq_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
PnvN1Chiplet *n1_chiplet = PNV_N1_CHIPLET(opaque);
|
||||
uint32_t reg = addr >> 3;
|
||||
|
||||
switch (reg) {
|
||||
case PB_SCOM_EQ0_HP_MODE2_CURR:
|
||||
n1_chiplet->eq[0].hp_mode2_curr = val;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "%s: Invalid xscom write at 0x%" PRIx32 "\n",
|
||||
__func__, reg);
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps pnv_n1_chiplet_pb_scom_eq_ops = {
|
||||
.read = pnv_n1_chiplet_pb_scom_eq_read,
|
||||
.write = pnv_n1_chiplet_pb_scom_eq_write,
|
||||
.valid.min_access_size = 8,
|
||||
.valid.max_access_size = 8,
|
||||
.impl.min_access_size = 8,
|
||||
.impl.max_access_size = 8,
|
||||
.endianness = DEVICE_BIG_ENDIAN,
|
||||
};
|
||||
|
||||
static uint64_t pnv_n1_chiplet_pb_scom_es_read(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
{
|
||||
PnvN1Chiplet *n1_chiplet = PNV_N1_CHIPLET(opaque);
|
||||
uint32_t reg = addr >> 3;
|
||||
uint64_t val = ~0ull;
|
||||
|
||||
switch (reg) {
|
||||
case PB_SCOM_ES3_MODE:
|
||||
val = n1_chiplet->es[3].mode;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "%s: Invalid xscom read at 0x%" PRIx32 "\n",
|
||||
__func__, reg);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void pnv_n1_chiplet_pb_scom_es_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
PnvN1Chiplet *n1_chiplet = PNV_N1_CHIPLET(opaque);
|
||||
uint32_t reg = addr >> 3;
|
||||
|
||||
switch (reg) {
|
||||
case PB_SCOM_ES3_MODE:
|
||||
n1_chiplet->es[3].mode = val;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "%s: Invalid xscom write at 0x%" PRIx32 "\n",
|
||||
__func__, reg);
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps pnv_n1_chiplet_pb_scom_es_ops = {
|
||||
.read = pnv_n1_chiplet_pb_scom_es_read,
|
||||
.write = pnv_n1_chiplet_pb_scom_es_write,
|
||||
.valid.min_access_size = 8,
|
||||
.valid.max_access_size = 8,
|
||||
.impl.min_access_size = 8,
|
||||
.impl.max_access_size = 8,
|
||||
.endianness = DEVICE_BIG_ENDIAN,
|
||||
};
|
||||
|
||||
static void pnv_n1_chiplet_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PnvN1Chiplet *n1_chiplet = PNV_N1_CHIPLET(dev);
|
||||
|
||||
/* Realize nest pervasive common chiplet model */
|
||||
if (!qdev_realize(DEVICE(&n1_chiplet->nest_pervasive), NULL, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Nest1 chiplet power bus EQ xscom region */
|
||||
pnv_xscom_region_init(&n1_chiplet->xscom_pb_eq_mr, OBJECT(n1_chiplet),
|
||||
&pnv_n1_chiplet_pb_scom_eq_ops, n1_chiplet,
|
||||
"xscom-n1-chiplet-pb-scom-eq",
|
||||
PNV10_XSCOM_N1_PB_SCOM_EQ_SIZE);
|
||||
|
||||
/* Nest1 chiplet power bus ES xscom region */
|
||||
pnv_xscom_region_init(&n1_chiplet->xscom_pb_es_mr, OBJECT(n1_chiplet),
|
||||
&pnv_n1_chiplet_pb_scom_es_ops, n1_chiplet,
|
||||
"xscom-n1-chiplet-pb-scom-es",
|
||||
PNV10_XSCOM_N1_PB_SCOM_ES_SIZE);
|
||||
}
|
||||
|
||||
static void pnv_n1_chiplet_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->desc = "PowerNV n1 chiplet";
|
||||
dc->realize = pnv_n1_chiplet_realize;
|
||||
}
|
||||
|
||||
static void pnv_n1_chiplet_instance_init(Object *obj)
|
||||
{
|
||||
PnvN1Chiplet *n1_chiplet = PNV_N1_CHIPLET(obj);
|
||||
|
||||
object_initialize_child(OBJECT(n1_chiplet), "nest-pervasive-common",
|
||||
&n1_chiplet->nest_pervasive,
|
||||
TYPE_PNV_NEST_CHIPLET_PERVASIVE);
|
||||
}
|
||||
|
||||
static const TypeInfo pnv_n1_chiplet_info = {
|
||||
.name = TYPE_PNV_N1_CHIPLET,
|
||||
.parent = TYPE_DEVICE,
|
||||
.instance_init = pnv_n1_chiplet_instance_init,
|
||||
.instance_size = sizeof(PnvN1Chiplet),
|
||||
.class_init = pnv_n1_chiplet_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_PNV_XSCOM_INTERFACE },
|
||||
{ }
|
||||
}
|
||||
};
|
||||
|
||||
static void pnv_n1_chiplet_register_types(void)
|
||||
{
|
||||
type_register_static(&pnv_n1_chiplet_info);
|
||||
}
|
||||
|
||||
type_init(pnv_n1_chiplet_register_types);
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* QEMU PowerPC nest pervasive common chiplet model
|
||||
*
|
||||
* Copyright (c) 2023, IBM Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/ppc/pnv.h"
|
||||
#include "hw/ppc/pnv_xscom.h"
|
||||
#include "hw/ppc/pnv_nest_pervasive.h"
|
||||
|
||||
/*
|
||||
* Status, configuration, and control units in POWER chips is provided
|
||||
* by the pervasive subsystem, which connects registers to the SCOM bus,
|
||||
* which can be programmed by processor cores, other units on the chip,
|
||||
* BMCs, or other POWER chips.
|
||||
*
|
||||
* A POWER10 chip is divided into logical units called chiplets. Chiplets
|
||||
* are broadly divided into "core chiplets" (with the processor cores) and
|
||||
* "nest chiplets" (with everything else). Each chiplet has an attachment
|
||||
* to the pervasive bus (PIB) and with chiplet-specific registers.
|
||||
* All nest chiplets have a common basic set of registers.
|
||||
*
|
||||
* This model will provide the registers functionality for common registers of
|
||||
* nest unit (PB Chiplet, PCI Chiplets, MC Chiplet, PAU Chiplets)
|
||||
*
|
||||
* Currently this model provide the read/write functionality of chiplet control
|
||||
* scom registers.
|
||||
*/
|
||||
|
||||
#define CPLT_CONF0 0x08
|
||||
#define CPLT_CONF0_OR 0x18
|
||||
#define CPLT_CONF0_CLEAR 0x28
|
||||
#define CPLT_CONF1 0x09
|
||||
#define CPLT_CONF1_OR 0x19
|
||||
#define CPLT_CONF1_CLEAR 0x29
|
||||
#define CPLT_STAT0 0x100
|
||||
#define CPLT_MASK0 0x101
|
||||
#define CPLT_PROTECT_MODE 0x3FE
|
||||
#define CPLT_ATOMIC_CLOCK 0x3FF
|
||||
|
||||
static uint64_t pnv_chiplet_ctrl_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
PnvNestChipletPervasive *nest_pervasive = PNV_NEST_CHIPLET_PERVASIVE(
|
||||
opaque);
|
||||
uint32_t reg = addr >> 3;
|
||||
uint64_t val = ~0ull;
|
||||
|
||||
/* CPLT_CTRL0 to CPLT_CTRL5 */
|
||||
for (int i = 0; i < PNV_CPLT_CTRL_SIZE; i++) {
|
||||
if (reg == i) {
|
||||
return nest_pervasive->control_regs.cplt_ctrl[i];
|
||||
} else if ((reg == (i + 0x10)) || (reg == (i + 0x20))) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Write only register, ignoring "
|
||||
"xscom read at 0x%" PRIx32 "\n",
|
||||
__func__, reg);
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
switch (reg) {
|
||||
case CPLT_CONF0:
|
||||
val = nest_pervasive->control_regs.cplt_cfg0;
|
||||
break;
|
||||
case CPLT_CONF0_OR:
|
||||
case CPLT_CONF0_CLEAR:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Write only register, ignoring "
|
||||
"xscom read at 0x%" PRIx32 "\n",
|
||||
__func__, reg);
|
||||
break;
|
||||
case CPLT_CONF1:
|
||||
val = nest_pervasive->control_regs.cplt_cfg1;
|
||||
break;
|
||||
case CPLT_CONF1_OR:
|
||||
case CPLT_CONF1_CLEAR:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Write only register, ignoring "
|
||||
"xscom read at 0x%" PRIx32 "\n",
|
||||
__func__, reg);
|
||||
break;
|
||||
case CPLT_STAT0:
|
||||
val = nest_pervasive->control_regs.cplt_stat0;
|
||||
break;
|
||||
case CPLT_MASK0:
|
||||
val = nest_pervasive->control_regs.cplt_mask0;
|
||||
break;
|
||||
case CPLT_PROTECT_MODE:
|
||||
val = nest_pervasive->control_regs.ctrl_protect_mode;
|
||||
break;
|
||||
case CPLT_ATOMIC_CLOCK:
|
||||
val = nest_pervasive->control_regs.ctrl_atomic_lock;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "%s: Chiplet_control_regs: Invalid xscom "
|
||||
"read at 0x%" PRIx32 "\n", __func__, reg);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void pnv_chiplet_ctrl_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
PnvNestChipletPervasive *nest_pervasive = PNV_NEST_CHIPLET_PERVASIVE(
|
||||
opaque);
|
||||
uint32_t reg = addr >> 3;
|
||||
|
||||
/* CPLT_CTRL0 to CPLT_CTRL5 */
|
||||
for (int i = 0; i < PNV_CPLT_CTRL_SIZE; i++) {
|
||||
if (reg == i) {
|
||||
nest_pervasive->control_regs.cplt_ctrl[i] = val;
|
||||
return;
|
||||
} else if (reg == (i + 0x10)) {
|
||||
nest_pervasive->control_regs.cplt_ctrl[i] |= val;
|
||||
return;
|
||||
} else if (reg == (i + 0x20)) {
|
||||
nest_pervasive->control_regs.cplt_ctrl[i] &= ~val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (reg) {
|
||||
case CPLT_CONF0:
|
||||
nest_pervasive->control_regs.cplt_cfg0 = val;
|
||||
break;
|
||||
case CPLT_CONF0_OR:
|
||||
nest_pervasive->control_regs.cplt_cfg0 |= val;
|
||||
break;
|
||||
case CPLT_CONF0_CLEAR:
|
||||
nest_pervasive->control_regs.cplt_cfg0 &= ~val;
|
||||
break;
|
||||
case CPLT_CONF1:
|
||||
nest_pervasive->control_regs.cplt_cfg1 = val;
|
||||
break;
|
||||
case CPLT_CONF1_OR:
|
||||
nest_pervasive->control_regs.cplt_cfg1 |= val;
|
||||
break;
|
||||
case CPLT_CONF1_CLEAR:
|
||||
nest_pervasive->control_regs.cplt_cfg1 &= ~val;
|
||||
break;
|
||||
case CPLT_STAT0:
|
||||
nest_pervasive->control_regs.cplt_stat0 = val;
|
||||
break;
|
||||
case CPLT_MASK0:
|
||||
nest_pervasive->control_regs.cplt_mask0 = val;
|
||||
break;
|
||||
case CPLT_PROTECT_MODE:
|
||||
nest_pervasive->control_regs.ctrl_protect_mode = val;
|
||||
break;
|
||||
case CPLT_ATOMIC_CLOCK:
|
||||
nest_pervasive->control_regs.ctrl_atomic_lock = val;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "%s: Chiplet_control_regs: Invalid xscom "
|
||||
"write at 0x%" PRIx32 "\n",
|
||||
__func__, reg);
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps pnv_nest_pervasive_control_xscom_ops = {
|
||||
.read = pnv_chiplet_ctrl_read,
|
||||
.write = pnv_chiplet_ctrl_write,
|
||||
.valid.min_access_size = 8,
|
||||
.valid.max_access_size = 8,
|
||||
.impl.min_access_size = 8,
|
||||
.impl.max_access_size = 8,
|
||||
.endianness = DEVICE_BIG_ENDIAN,
|
||||
};
|
||||
|
||||
static void pnv_nest_pervasive_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PnvNestChipletPervasive *nest_pervasive = PNV_NEST_CHIPLET_PERVASIVE(dev);
|
||||
|
||||
/* Chiplet control scoms */
|
||||
pnv_xscom_region_init(&nest_pervasive->xscom_ctrl_regs_mr,
|
||||
OBJECT(nest_pervasive),
|
||||
&pnv_nest_pervasive_control_xscom_ops,
|
||||
nest_pervasive, "pervasive-control",
|
||||
PNV10_XSCOM_CHIPLET_CTRL_REGS_SIZE);
|
||||
}
|
||||
|
||||
static void pnv_nest_pervasive_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->desc = "PowerNV nest pervasive chiplet";
|
||||
dc->realize = pnv_nest_pervasive_realize;
|
||||
}
|
||||
|
||||
static const TypeInfo pnv_nest_pervasive_info = {
|
||||
.name = TYPE_PNV_NEST_CHIPLET_PERVASIVE,
|
||||
.parent = TYPE_DEVICE,
|
||||
.instance_size = sizeof(PnvNestChipletPervasive),
|
||||
.class_init = pnv_nest_pervasive_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_PNV_XSCOM_INTERFACE },
|
||||
{ }
|
||||
}
|
||||
};
|
||||
|
||||
static void pnv_nest_pervasive_register_types(void)
|
||||
{
|
||||
type_register_static(&pnv_nest_pervasive_info);
|
||||
}
|
||||
|
||||
type_init(pnv_nest_pervasive_register_types);
|
||||
+5
-7
@@ -4639,13 +4639,10 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
|
||||
mc->block_default_type = IF_SCSI;
|
||||
|
||||
/*
|
||||
* Setting max_cpus to INT32_MAX. Both KVM and TCG max_cpus values
|
||||
* should be limited by the host capability instead of hardcoded.
|
||||
* max_cpus for KVM guests will be checked in kvm_init(), and TCG
|
||||
* guests are welcome to have as many CPUs as the host are capable
|
||||
* of emulate.
|
||||
* While KVM determines max cpus in kvm_init() using kvm_max_vcpus(),
|
||||
* In TCG the limit is restricted by the range of CPU IPIs available.
|
||||
*/
|
||||
mc->max_cpus = INT32_MAX;
|
||||
mc->max_cpus = SPAPR_IRQ_NR_IPIS;
|
||||
|
||||
mc->no_parallel = 1;
|
||||
mc->default_boot_order = "";
|
||||
@@ -4667,7 +4664,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
|
||||
|
||||
smc->dr_lmb_enabled = true;
|
||||
smc->update_dt_enabled = true;
|
||||
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.2");
|
||||
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
|
||||
mc->has_hotpluggable_cpus = true;
|
||||
mc->nvdimm_supported = true;
|
||||
smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED;
|
||||
@@ -5086,6 +5083,7 @@ static void spapr_machine_2_11_class_options(MachineClass *mc)
|
||||
spapr_machine_2_12_class_options(mc);
|
||||
smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON;
|
||||
compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len);
|
||||
mc->deprecation_reason = "old and not maintained - use a 2.12+ version";
|
||||
}
|
||||
|
||||
DEFINE_SPAPR_MACHINE(2_11, "2.11", false);
|
||||
|
||||
@@ -123,9 +123,11 @@ static target_ulong h_resize_hpt_prepare(PowerPCCPU *cpu,
|
||||
|
||||
if (kvm_enabled()) {
|
||||
return H_HARDWARE;
|
||||
} else if (tcg_enabled()) {
|
||||
return vhyp_mmu_resize_hpt_prepare(cpu, spapr, shift);
|
||||
} else {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
return softmmu_resize_hpt_prepare(cpu, spapr, shift);
|
||||
}
|
||||
|
||||
static void do_push_sregs_to_kvm_pr(CPUState *cs, run_on_cpu_data data)
|
||||
@@ -191,9 +193,11 @@ static target_ulong h_resize_hpt_commit(PowerPCCPU *cpu,
|
||||
|
||||
if (kvm_enabled()) {
|
||||
return H_HARDWARE;
|
||||
} else if (tcg_enabled()) {
|
||||
return vhyp_mmu_resize_hpt_commit(cpu, spapr, flags, shift);
|
||||
} else {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
return softmmu_resize_hpt_commit(cpu, spapr, flags, shift);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+4
-2
@@ -23,6 +23,8 @@
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
QEMU_BUILD_BUG_ON(SPAPR_IRQ_NR_IPIS > SPAPR_XIRQ_BASE);
|
||||
|
||||
static const TypeInfo spapr_intc_info = {
|
||||
.name = TYPE_SPAPR_INTC,
|
||||
.parent = TYPE_INTERFACE,
|
||||
@@ -329,7 +331,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
|
||||
int i;
|
||||
|
||||
dev = qdev_new(TYPE_SPAPR_XIVE);
|
||||
qdev_prop_set_uint32(dev, "nr-irqs", smc->nr_xirqs + SPAPR_XIRQ_BASE);
|
||||
qdev_prop_set_uint32(dev, "nr-irqs", smc->nr_xirqs + SPAPR_IRQ_NR_IPIS);
|
||||
/*
|
||||
* 8 XIVE END structures per CPU. One for each available
|
||||
* priority
|
||||
@@ -356,7 +358,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
|
||||
}
|
||||
|
||||
spapr->qirqs = qemu_allocate_irqs(spapr_set_irq, spapr,
|
||||
smc->nr_xirqs + SPAPR_XIRQ_BASE);
|
||||
smc->nr_xirqs + SPAPR_IRQ_NR_IPIS);
|
||||
|
||||
/*
|
||||
* Mostly we don't actually need this until reset, except that not
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
/*
|
||||
* MMU hypercalls for the sPAPR (pseries) vHyp hypervisor that is used by TCG
|
||||
*
|
||||
* Copyright (c) 2004-2007 Fabrice Bellard
|
||||
* Copyright (c) 2007 Jocelyn Mayer
|
||||
* Copyright (c) 2010 David Gibson, IBM Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/memalign.h"
|
||||
@@ -369,7 +378,7 @@ static void cancel_hpt_prepare(SpaprMachineState *spapr)
|
||||
free_pending_hpt(pending);
|
||||
}
|
||||
|
||||
target_ulong softmmu_resize_hpt_prepare(PowerPCCPU *cpu,
|
||||
target_ulong vhyp_mmu_resize_hpt_prepare(PowerPCCPU *cpu,
|
||||
SpaprMachineState *spapr,
|
||||
target_ulong shift)
|
||||
{
|
||||
@@ -553,7 +562,7 @@ static int rehash_hpt(PowerPCCPU *cpu,
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
target_ulong softmmu_resize_hpt_commit(PowerPCCPU *cpu,
|
||||
target_ulong vhyp_mmu_resize_hpt_commit(PowerPCCPU *cpu,
|
||||
SpaprMachineState *spapr,
|
||||
target_ulong flags,
|
||||
target_ulong shift)
|
||||
@@ -95,6 +95,10 @@ vof_write(uint32_t ih, unsigned cb, const char *msg) "ih=0x%x [%u] \"%s\""
|
||||
vof_avail(uint64_t start, uint64_t end, uint64_t size) "0x%"PRIx64"..0x%"PRIx64" size=0x%"PRIx64
|
||||
vof_claimed(uint64_t start, uint64_t end, uint64_t size) "0x%"PRIx64"..0x%"PRIx64" size=0x%"PRIx64
|
||||
|
||||
# pnv_chiptod.c
|
||||
pnv_chiptod_xscom_read(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " val 0x%" PRIx64
|
||||
pnv_chiptod_xscom_write(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " val 0x%" PRIx64
|
||||
|
||||
# pnv_sbe.c
|
||||
pnv_sbe_xscom_ctrl_read(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " val 0x%" PRIx64
|
||||
pnv_sbe_xscom_ctrl_write(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " val 0x%" PRIx64
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* PowerNV I2C Controller Register Definitions
|
||||
*
|
||||
* Copyright (c) 2024, IBM Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef PNV_I2C_REGS_H
|
||||
#define PNV_I2C_REGS_H
|
||||
|
||||
/* I2C FIFO register */
|
||||
#define I2C_FIFO_REG 0x4
|
||||
#define I2C_FIFO PPC_BITMASK(0, 7)
|
||||
|
||||
/* I2C command register */
|
||||
#define I2C_CMD_REG 0x5
|
||||
#define I2C_CMD_WITH_START PPC_BIT(0)
|
||||
#define I2C_CMD_WITH_ADDR PPC_BIT(1)
|
||||
#define I2C_CMD_READ_CONT PPC_BIT(2)
|
||||
#define I2C_CMD_WITH_STOP PPC_BIT(3)
|
||||
#define I2C_CMD_INTR_STEERING PPC_BITMASK(6, 7) /* P9 */
|
||||
#define I2C_CMD_INTR_STEER_HOST 1
|
||||
#define I2C_CMD_INTR_STEER_OCC 2
|
||||
#define I2C_CMD_DEV_ADDR PPC_BITMASK(8, 14)
|
||||
#define I2C_CMD_READ_NOT_WRITE PPC_BIT(15)
|
||||
#define I2C_CMD_LEN_BYTES PPC_BITMASK(16, 31)
|
||||
#define I2C_MAX_TFR_LEN 0xfff0ull
|
||||
|
||||
/* I2C mode register */
|
||||
#define I2C_MODE_REG 0x6
|
||||
#define I2C_MODE_BIT_RATE_DIV PPC_BITMASK(0, 15)
|
||||
#define I2C_MODE_PORT_NUM PPC_BITMASK(16, 21)
|
||||
#define I2C_MODE_ENHANCED PPC_BIT(28)
|
||||
#define I2C_MODE_DIAGNOSTIC PPC_BIT(29)
|
||||
#define I2C_MODE_PACING_ALLOW PPC_BIT(30)
|
||||
#define I2C_MODE_WRAP PPC_BIT(31)
|
||||
|
||||
/* I2C watermark register */
|
||||
#define I2C_WATERMARK_REG 0x7
|
||||
#define I2C_WATERMARK_HIGH PPC_BITMASK(16, 19)
|
||||
#define I2C_WATERMARK_LOW PPC_BITMASK(24, 27)
|
||||
|
||||
/*
|
||||
* I2C interrupt mask and condition registers
|
||||
*
|
||||
* NB: The function of 0x9 and 0xa changes depending on whether you're reading
|
||||
* or writing to them. When read they return the interrupt condition bits
|
||||
* and on writes they update the interrupt mask register.
|
||||
*
|
||||
* The bit definitions are the same for all the interrupt registers.
|
||||
*/
|
||||
#define I2C_INTR_MASK_REG 0x8
|
||||
|
||||
#define I2C_INTR_RAW_COND_REG 0x9 /* read */
|
||||
#define I2C_INTR_MASK_OR_REG 0x9 /* write*/
|
||||
|
||||
#define I2C_INTR_COND_REG 0xa /* read */
|
||||
#define I2C_INTR_MASK_AND_REG 0xa /* write */
|
||||
|
||||
#define I2C_INTR_ALL PPC_BITMASK(16, 31)
|
||||
#define I2C_INTR_INVALID_CMD PPC_BIT(16)
|
||||
#define I2C_INTR_LBUS_PARITY_ERR PPC_BIT(17)
|
||||
#define I2C_INTR_BKEND_OVERRUN_ERR PPC_BIT(18)
|
||||
#define I2C_INTR_BKEND_ACCESS_ERR PPC_BIT(19)
|
||||
#define I2C_INTR_ARBT_LOST_ERR PPC_BIT(20)
|
||||
#define I2C_INTR_NACK_RCVD_ERR PPC_BIT(21)
|
||||
#define I2C_INTR_DATA_REQ PPC_BIT(22)
|
||||
#define I2C_INTR_CMD_COMP PPC_BIT(23)
|
||||
#define I2C_INTR_STOP_ERR PPC_BIT(24)
|
||||
#define I2C_INTR_I2C_BUSY PPC_BIT(25)
|
||||
#define I2C_INTR_NOT_I2C_BUSY PPC_BIT(26)
|
||||
#define I2C_INTR_SCL_EQ_1 PPC_BIT(28)
|
||||
#define I2C_INTR_SCL_EQ_0 PPC_BIT(29)
|
||||
#define I2C_INTR_SDA_EQ_1 PPC_BIT(30)
|
||||
#define I2C_INTR_SDA_EQ_0 PPC_BIT(31)
|
||||
|
||||
/* I2C status register */
|
||||
#define I2C_RESET_I2C_REG 0xb /* write */
|
||||
#define I2C_RESET_ERRORS 0xc
|
||||
#define I2C_STAT_REG 0xb /* read */
|
||||
#define I2C_STAT_INVALID_CMD PPC_BIT(0)
|
||||
#define I2C_STAT_LBUS_PARITY_ERR PPC_BIT(1)
|
||||
#define I2C_STAT_BKEND_OVERRUN_ERR PPC_BIT(2)
|
||||
#define I2C_STAT_BKEND_ACCESS_ERR PPC_BIT(3)
|
||||
#define I2C_STAT_ARBT_LOST_ERR PPC_BIT(4)
|
||||
#define I2C_STAT_NACK_RCVD_ERR PPC_BIT(5)
|
||||
#define I2C_STAT_DATA_REQ PPC_BIT(6)
|
||||
#define I2C_STAT_CMD_COMP PPC_BIT(7)
|
||||
#define I2C_STAT_STOP_ERR PPC_BIT(8)
|
||||
#define I2C_STAT_UPPER_THRS PPC_BITMASK(9, 15)
|
||||
#define I2C_STAT_ANY_I2C_INTR PPC_BIT(16)
|
||||
#define I2C_STAT_PORT_HISTORY_BUSY PPC_BIT(19)
|
||||
#define I2C_STAT_SCL_INPUT_LEVEL PPC_BIT(20)
|
||||
#define I2C_STAT_SDA_INPUT_LEVEL PPC_BIT(21)
|
||||
#define I2C_STAT_PORT_BUSY PPC_BIT(22)
|
||||
#define I2C_STAT_INTERFACE_BUSY PPC_BIT(23)
|
||||
#define I2C_STAT_FIFO_ENTRY_COUNT PPC_BITMASK(24, 31)
|
||||
|
||||
#define I2C_STAT_ANY_ERR (I2C_STAT_INVALID_CMD | I2C_STAT_LBUS_PARITY_ERR | \
|
||||
I2C_STAT_BKEND_OVERRUN_ERR | \
|
||||
I2C_STAT_BKEND_ACCESS_ERR | I2C_STAT_ARBT_LOST_ERR | \
|
||||
I2C_STAT_NACK_RCVD_ERR | I2C_STAT_STOP_ERR)
|
||||
|
||||
|
||||
#define I2C_INTR_ACTIVE \
|
||||
((I2C_STAT_ANY_ERR >> 16) | I2C_INTR_CMD_COMP | I2C_INTR_DATA_REQ)
|
||||
|
||||
/* Pseudo-status used for timeouts */
|
||||
#define I2C_STAT_PSEUDO_TIMEOUT PPC_BIT(63)
|
||||
|
||||
/* I2C extended status register */
|
||||
#define I2C_EXTD_STAT_REG 0xc
|
||||
#define I2C_EXTD_STAT_FIFO_SIZE PPC_BITMASK(0, 7)
|
||||
#define I2C_EXTD_STAT_MSM_CURSTATE PPC_BITMASK(11, 15)
|
||||
#define I2C_EXTD_STAT_SCL_IN_SYNC PPC_BIT(16)
|
||||
#define I2C_EXTD_STAT_SDA_IN_SYNC PPC_BIT(17)
|
||||
#define I2C_EXTD_STAT_S_SCL PPC_BIT(18)
|
||||
#define I2C_EXTD_STAT_S_SDA PPC_BIT(19)
|
||||
#define I2C_EXTD_STAT_M_SCL PPC_BIT(20)
|
||||
#define I2C_EXTD_STAT_M_SDA PPC_BIT(21)
|
||||
#define I2C_EXTD_STAT_HIGH_WATER PPC_BIT(22)
|
||||
#define I2C_EXTD_STAT_LOW_WATER PPC_BIT(23)
|
||||
#define I2C_EXTD_STAT_I2C_BUSY PPC_BIT(24)
|
||||
#define I2C_EXTD_STAT_SELF_BUSY PPC_BIT(25)
|
||||
#define I2C_EXTD_STAT_I2C_VERSION PPC_BITMASK(27, 31)
|
||||
|
||||
/* I2C residual front end/back end length */
|
||||
#define I2C_RESIDUAL_LEN_REG 0xd
|
||||
#define I2C_RESIDUAL_FRONT_END PPC_BITMASK(0, 15)
|
||||
#define I2C_RESIDUAL_BACK_END PPC_BITMASK(16, 31)
|
||||
|
||||
/* Port busy register */
|
||||
#define I2C_PORT_BUSY_REG 0xe
|
||||
#define I2C_SET_S_SCL_REG 0xd
|
||||
#define I2C_RESET_S_SCL_REG 0xf
|
||||
#define I2C_SET_S_SDA_REG 0x10
|
||||
#define I2C_RESET_S_SDA_REG 0x11
|
||||
|
||||
#define PNV_I2C_FIFO_SIZE 8
|
||||
#define PNV_I2C_MAX_BUSSES 64
|
||||
|
||||
#endif /* PNV_I2C_REGS_H */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user