uboot/arch/x86/cpu/broadwell/iobp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2016 Google, Inc
   4 *
   5 * Modified from coreboot
   6 */
   7
   8#include <common.h>
   9#include <errno.h>
  10#include <asm/intel_regs.h>
  11#include <asm/io.h>
  12#include <asm/arch/pch.h>
  13#include <linux/delay.h>
  14
  15#define IOBP_RETRY 1000
  16
  17/* IO Buffer Programming */
  18#define IOBPIRI         0x2330
  19#define IOBPD           0x2334
  20#define IOBPS           0x2338
  21#define  IOBPS_READY    0x0001
  22#define  IOBPS_TX_MASK  0x0006
  23#define  IOBPS_MASK     0xff00
  24#define  IOBPS_READ     0x0600
  25#define  IOBPS_WRITE    0x0700
  26#define IOBPU           0x233a
  27#define  IOBPU_MAGIC    0xf000
  28#define  IOBP_PCICFG_READ       0x0400
  29#define  IOBP_PCICFG_WRITE      0x0500
  30
  31static inline int iobp_poll(void)
  32{
  33        unsigned try;
  34
  35        for (try = IOBP_RETRY; try > 0; try--) {
  36                u16 status = readw(RCB_REG(IOBPS));
  37                if ((status & IOBPS_READY) == 0)
  38                        return 1;
  39                udelay(10);
  40        }
  41
  42        printf("IOBP: timeout waiting for transaction to complete\n");
  43        return 0;
  44}
  45
  46int pch_iobp_trans_start(u32 address, int op)
  47{
  48        if (!iobp_poll())
  49                return 0;
  50
  51        /* Set the address */
  52        writel(address, RCB_REG(IOBPIRI));
  53
  54        /* READ OPCODE */
  55        clrsetbits_le16(RCB_REG(IOBPS), IOBPS_MASK, op);
  56
  57        return 1;
  58}
  59
  60int pch_iobp_trans_finish(void)
  61{
  62        u16 status;
  63
  64        /* Undocumented magic */
  65        writew(IOBPU_MAGIC, RCB_REG(IOBPU));
  66
  67        /* Set ready bit */
  68        setbits_le16(RCB_REG(IOBPS), IOBPS_READY);
  69
  70        if (!iobp_poll())
  71                return 1;
  72
  73        /* Check for successful transaction */
  74        status = readw(RCB_REG(IOBPS));
  75        if (status & IOBPS_TX_MASK)
  76                return 1;
  77
  78        return 0;
  79}
  80
  81u32 pch_iobp_read(u32 address)
  82{
  83        if (!pch_iobp_trans_start(address, IOBPS_READ))
  84                return 0;
  85        if (pch_iobp_trans_finish()) {
  86                printf("IOBP: read 0x%08x failed\n", address);
  87                return 0;
  88        }
  89
  90        /* Read IOBP data */
  91        return readl(RCB_REG(IOBPD));
  92}
  93
  94int pch_iobp_write(u32 address, u32 data)
  95{
  96        if (!pch_iobp_trans_start(address, IOBPS_WRITE))
  97                return -EIO;
  98
  99        writel(data, RCB_REG(IOBPD));
 100
 101        if (pch_iobp_trans_finish()) {
 102                printf("IOBP: write 0x%08x failed\n", address);
 103                return -EIO;
 104        }
 105
 106        return 0;
 107}
 108
 109int pch_iobp_update(u32 address, u32 andvalue, u32 orvalue)
 110{
 111        u32 data = pch_iobp_read(address);
 112
 113        /* Update the data */
 114        data &= andvalue;
 115        data |= orvalue;
 116
 117        return pch_iobp_write(address, data);
 118}
 119
 120int pch_iobp_exec(u32 addr, u16 op_code, u8 route_id, u32 *data, u8 *resp)
 121{
 122        if (!data || !resp)
 123                return 0;
 124
 125        *resp = -1;
 126        if (!iobp_poll())
 127                return -EIO;
 128
 129        writel(addr, RCB_REG(IOBPIRI));
 130        clrsetbits_le16(RCB_REG(IOBPS), 0xff00, op_code);
 131        writew(IOBPU_MAGIC | route_id, RCB_REG(IOBPU));
 132
 133        writel(*data, RCB_REG(IOBPD));
 134        /* Set IOBPS[0] to trigger IOBP transaction*/
 135        setbits_le16(RCB_REG(IOBPS), 1);
 136
 137        if (!iobp_poll())
 138                return -EIO;
 139
 140        *resp = (readw(RCB_REG(IOBPS)) & IOBPS_TX_MASK) >> 1;
 141        *data = readl(RCB_REG(IOBPD));
 142
 143        return 0;
 144}
 145