[Skiboot] [PATCH V3] occ: irq: Fix SCOM address and irq reasons for OCC_MISC register
Michael Neuling
mikey at neuling.org
Wed Apr 12 17:07:21 AEST 2017
On Fri, 2017-04-07 at 14:22 +0530, Shilpasri G Bhat wrote:
> This patch fixes the SCOM address for OCC_MISC register which is used
> for OCC interupts. In P9, OCC sends an interrupt to notify change in
> the shared memory like throttle status. This patch handles this
> interrupt reason.
Thanks, this has been merged as of 044fe827e0.
Mikey
>
> Originally-from: Michael Neuling <mikey at neuling.org>
> Signed-off-by: Shilpasri G Bhat <shilpa.bhat at linux.vnet.ibm.com>
> ---
> Changes from V2:
> - Fix the proc_gen check to return if (proc_gen < proc_gen_p8).
> proc_gen > proc_gen_p9 is not required as we do scom in the switch
> case. The new hardware gets gated in the switch case.
>
> Changes from V1:
> - s/_AND/_CLEAR
> - Add irq reason bits for i2c ownership change and shared memory
> change
> - Handle shared memory change interrupt reason
> - Reuse OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY bit in
> occ_send_dummy_interrupt() for P9.
>
> hw/occ.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++------
> ---
> hw/psi.c | 4 +--
> include/skiboot.h | 7 +++--
> 3 files changed, 79 insertions(+), 17 deletions(-)
>
> diff --git a/hw/occ.c b/hw/occ.c
> index 7b502b4..145d669 100644
> --- a/hw/occ.c
> +++ b/hw/occ.c
> @@ -1279,24 +1279,37 @@ static struct fsp_client fsp_occ_client = {
> .message = fsp_occ_msg,
> };
>
> -#define OCB_OCI_OCCMISC 0x6a020
> -#define OCB_OCI_OCCMISC_AND 0x6a021
> -#define OCB_OCI_OCCMISC_OR 0x6a022
> +#define P8_OCB_OCI_OCCMISC 0x6a020
> +#define P8_OCB_OCI_OCCMISC_AND 0x6a021
> +#define P8_OCB_OCI_OCCMISC_OR 0x6a022
> +
> +#define P9_OCB_OCI_OCCMISC 0x6c080
> +#define P9_OCB_OCI_OCCMISC_CLEAR 0x6c081
> +#define P9_OCB_OCI_OCCMISC_OR 0x6c082
> +
> #define OCB_OCI_OCIMISC_IRQ PPC_BIT(0)
> #define OCB_OCI_OCIMISC_IRQ_TMGT PPC_BIT(1)
> #define OCB_OCI_OCIMISC_IRQ_SLW_TMR PPC_BIT(14)
> #define OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY PPC_BIT(15)
> -#define OCB_OCI_OCIMISC_MASK (OCB_OCI_OCIMISC_IRQ_TMGT | \
> +
> +#define P8_OCB_OCI_OCIMISC_MASK (OCB_OCI_OCIMISC_IRQ_TMGT | \
> OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY | \
> OCB_OCI_OCIMISC_IRQ_SLW_TMR)
>
> +#define OCB_OCI_OCIMISC_IRQ_I2C PPC_BIT(2)
> +#define OCB_OCI_OCIMISC_IRQ_SHMEM PPC_BIT(3)
> +#define P9_OCB_OCI_OCIMISC_MASK (OCB_OCI_OCIMISC_IRQ_TMGT | \
> + OCB_OCI_OCIMISC_IRQ_I2C | \
> + OCB_OCI_OCIMISC_IRQ_SHMEM | \
> + OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY)
> +
> void occ_send_dummy_interrupt(void)
> {
> struct psi *psi;
> struct proc_chip *chip = get_chip(this_cpu()->chip_id);
>
> /* Emulators and P7 doesn't do this */
> - if (proc_gen != proc_gen_p8 || chip_quirk(QUIRK_NO_OCC_IRQ))
> + if (proc_gen < proc_gen_p8 || chip_quirk(QUIRK_NO_OCC_IRQ))
> return;
>
> /* Find a functional PSI. This ensures an interrupt even if
> @@ -1312,17 +1325,29 @@ void occ_send_dummy_interrupt(void)
> return;
> }
>
> - xscom_write(psi->chip_id, OCB_OCI_OCCMISC_OR,
> - OCB_OCI_OCIMISC_IRQ | OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY);
> + switch (proc_gen) {
> + case proc_gen_p8:
> + xscom_write(psi->chip_id, P8_OCB_OCI_OCCMISC_OR,
> + OCB_OCI_OCIMISC_IRQ |
> + OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY);
> + break;
> + case proc_gen_p9:
> + xscom_write(psi->chip_id, P9_OCB_OCI_OCCMISC_OR,
> + OCB_OCI_OCIMISC_IRQ |
> + OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY);
> + break;
> + default:
> + break;
> + }
> }
>
> -void occ_interrupt(uint32_t chip_id)
> +void occ_p8_interrupt(uint32_t chip_id)
> {
> uint64_t ireg;
> int64_t rc;
>
> /* The OCC interrupt is used to mux up to 15 different sources */
> - rc = xscom_read(chip_id, OCB_OCI_OCCMISC, &ireg);
> + rc = xscom_read(chip_id, P8_OCB_OCI_OCCMISC, &ireg);
> if (rc) {
> prerror("OCC: Failed to read interrupt status !\n");
> /* Should we mask it in the XIVR ? */
> @@ -1331,7 +1356,7 @@ void occ_interrupt(uint32_t chip_id)
> prlog(PR_TRACE, "OCC: IRQ received: %04llx\n", ireg >> 48);
>
> /* Clear the bits */
> - xscom_write(chip_id, OCB_OCI_OCCMISC_AND, ~ireg);
> + xscom_write(chip_id, P8_OCB_OCI_OCCMISC_AND, ~ireg);
>
> /* Dispatch */
> if (ireg & OCB_OCI_OCIMISC_IRQ_TMGT)
> @@ -1343,9 +1368,43 @@ void occ_interrupt(uint32_t chip_id)
> * OCCMISC_AND write. Check if there are any new source bits set,
> * and trigger another interrupt if so.
> */
> - rc = xscom_read(chip_id, OCB_OCI_OCCMISC, &ireg);
> - if (!rc && (ireg & OCB_OCI_OCIMISC_MASK))
> - xscom_write(chip_id, OCB_OCI_OCCMISC_OR,
> OCB_OCI_OCIMISC_IRQ);
> + rc = xscom_read(chip_id, P8_OCB_OCI_OCCMISC, &ireg);
> + if (!rc && (ireg & P8_OCB_OCI_OCIMISC_MASK))
> + xscom_write(chip_id, P8_OCB_OCI_OCCMISC_OR,
> + OCB_OCI_OCIMISC_IRQ);
> +}
> +
> +void occ_p9_interrupt(uint32_t chip_id)
> +{
> + u64 ireg;
> + s64 rc;
> +
> + /* The OCC interrupt is used to mux up to 15 different sources */
> + rc = xscom_read(chip_id, P9_OCB_OCI_OCCMISC, &ireg);
> + if (rc) {
> + prerror("OCC: Failed to read interrupt status !\n");
> + return;
> + }
> + prlog(PR_TRACE, "OCC: IRQ received: %04llx\n", ireg >> 48);
> +
> + /* Clear the bits */
> + xscom_write(chip_id, P9_OCB_OCI_OCCMISC_CLEAR, ireg);
> +
> + /* Dispatch */
> + if (ireg & OCB_OCI_OCIMISC_IRQ_TMGT)
> + prd_tmgt_interrupt(chip_id);
> +
> + if (ireg & OCB_OCI_OCIMISC_IRQ_SHMEM)
> + occ_throttle_poll(NULL);
> +
> + /* We may have masked-out OCB_OCI_OCIMISC_IRQ in the previous
> + * OCCMISC_AND write. Check if there are any new source bits set,
> + * and trigger another interrupt if so.
> + */
> + rc = xscom_read(chip_id, P9_OCB_OCI_OCCMISC, &ireg);
> + if (!rc && (ireg & P9_OCB_OCI_OCIMISC_MASK))
> + xscom_write(chip_id, P9_OCB_OCI_OCCMISC_OR,
> + OCB_OCI_OCIMISC_IRQ);
> }
>
> void occ_fsp_init(void)
> diff --git a/hw/psi.c b/hw/psi.c
> index 089f429..cc7db44 100644
> --- a/hw/psi.c
> +++ b/hw/psi.c
> @@ -485,7 +485,7 @@ static void psihb_p8_interrupt(struct irq_source *is,
> uint32_t isn)
> psihb_interrupt(is, isn);
> break;
> case P8_IRQ_PSI_OCC:
> - occ_interrupt(psi->chip_id);
> + occ_p8_interrupt(psi->chip_id);
> break;
> case P8_IRQ_PSI_FSI:
> printf("PSI: FSI irq received\n");
> @@ -572,7 +572,7 @@ static void psihb_p9_interrupt(struct irq_source *is,
> uint32_t isn)
> psihb_interrupt(is, isn);
> break;
> case P9_PSI_IRQ_OCC:
> - occ_interrupt(psi->chip_id);
> + occ_p9_interrupt(psi->chip_id);
> break;
> case P9_PSI_IRQ_FSI:
> printf("PSI: FSI irq received\n");
> diff --git a/include/skiboot.h b/include/skiboot.h
> index 8bc767a..2b1f8a5 100644
> --- a/include/skiboot.h
> +++ b/include/skiboot.h
> @@ -254,10 +254,13 @@ enum {
> extern void uart_set_console_policy(int policy);
> extern bool uart_enabled(void);
>
> -/* OCC interrupt */
> -extern void occ_interrupt(uint32_t chip_id);
> +/* OCC interrupt for P8 */
> +extern void occ_p8_interrupt(uint32_t chip_id);
> extern void occ_send_dummy_interrupt(void);
>
> +/* OCC interrupt for P9 */
> +extern void occ_p9_interrupt(uint32_t chip_id);
> +
> /* OCC load support */
> extern void occ_poke_load_queue(void);
>
More information about the Skiboot
mailing list